PrimeNg TabView with ConfirmDialog not working - angular8

I'm trying to use PrimeNg TabView component along with confirmDialog unsuccessfully
I am able to show this confirm dialog but it appears after user switch to target tab panel which is wrong.
<p-tabView (onChange)="handleChange($event)" [(activeIndex)]="index">...</p-tabView>
handleChange(e) {
this.confirmationService.confirm({
message: 'There are unsaved changes, do you want to proceed?',
accept: () => {
this.index = e.index;
},
reject:() =>{ }
});
}
Do you have an idea on how to prevent or allow tab change using confirm dialog ?
Thanks

there is no official way to prevent change to another tab by press on that tab , but 😅 there is a work around it first we need to prevent the tab change by tab click,
1️⃣ we need to set the header by ng-template or it called a custom header
template
<p-tabPanel >
<ng-template pTemplate="header">
<div (click)="handleChange($event,0)">
Godfather I
</div>
</ng-template>
.....
</p-tabPanel>
2️⃣ we bind a click event to the new header text and by using mouse event stopPropagation method we can prevent the change 👌,now we can control the change by confirm result but you need to pass the current tab index, that why I add another parameter to handleChange
component
handleChange(e:MouseEvent,tabIndex:number) {
e.stopPropagation();
if (this.index == tabIndex){
return;
}
// console.log(tabIndex)
this.confirmationService.confirm({
message: "There are unsaved changes, do you want to proceed?",
accept: () => {
this.index = tabIndex;
},
reject: () => {}
});
}
the if block if (this.index == tabIndex){return;} use to prevent showing the confirm dialog if we click on the same active tab again
demo 🚀🚀

Related

VueJS - How to highlight selected button when clicked

I have 3 buttons that shows a chart when clicked on it respectively. Here below is the buttons for example:
Whenever the button is clicked respective chart is shown, but I want to keep the button highlighted with red color while the chart is shown.
<vs-button color="warning" #click="chartClick($event, 'chart1')" vs-value="chart1" v-model="show"> chart1</vs-button>
<vs-button color="warning" #click="chartClick($event, 'chart2')" vs-value="chart2" v-model="show"> chart2 </vs-button>
<vs-button color="warning" #click="chartClick($event, 'chart3')" vs-value="chart3" v-model="show"> chart3 </vs-button>
<script>
data () {
return {
show = false
}
},
mounted (){
chartClick (chart1)
},
methods: {
chartClick (event, id){
...
this.show = true
}
}
</script>
Please help me in this, i want to know how to highlight the button, when the chart is shown.
And also i want to know how to display chart1 with button1 (chart1) highlighted when the page is loaded or runned at first.
You can do that by adding one more variable in data section, for example:
data () {
return {
show : false,
activeChart : '',
}
}
You should not use variableName = defaultValue, it should be variableName : defaultValue.
and then add to your buttons:
:class="{activeChartClass: activeChart === 'chart1'}"
Note: are you sure v-model is supported on vs-button tag?
also you will have to add this to your chartClick method:
this.activeChart = id;
and finally add a CSS class to edit your active button:
.activeChartClass {
background-color: red!important;
}
You can read more about class and style binding here: https://v2.vuejs.org/v2/guide/class-and-style.html#Object-Syntax

Vue.js - How to load data with method call via click and toggle data?

I'm loading data via my rest api when the button is clicked with a vue.js method. To hide the loaded data I'm clicking the button again. When I'm clicking the button to show the data again, the same method is called again and the data is shown twice.
<div v-if="comment.answers_count !== 0">
<button
#click="toggleAnswers"
:class="{
'btn-danger': loadAnswers,
'btn-outline-danger': !loadAnswers
}"><strong>{{ comment.answers_count }} show answers</strong></button>
</div>
How can I load the data once, hide it with button clicked and show the same loaded data when toggling the button?
Maybe theres a way to use a computed property?
Create a new property in data:function(){}
e.x
data:function(){
answers_loaded:false
}
then on your function toggleAnswers
do the following
methods:{
toggleAnswers:function(){
/** if answers are not loaded , load them **/
if(!this.answers_loaded){
/** mark answers_loaded to true, so we do not call this code
again. Should be better put on your success request handler
to make sure that they were successfully loaded**/
this.answers_loaded = true;
//code to load the answers
}
}
}
So the first time that you click the button and function toggleAnswers is called the variable answers_loaded pass the if check.
Every other time that you click the button since answers_loaded is equal to true, it will fail the if check and wont call again part of the code to load the answers
So,i can't get you real purpose?
if you want to just load data once, you can use v-once, eg
<button #click.once="loadData" #click="hideData"> loadData or hideData</button>
...
loadData() {
setTimeout(() => {
this.data = 'loaded data'
}, 500)
},
hideData() {
this.data = this.data && null
}
if you want the toggle circle then you should set a tag using %2 to judge which function to run .

Switching to a nested route is automatically running the last commit event from parent's store

Reproduction link
https://codesandbox.io/s/vue-template-c2gtb
Steps to reproduce
Open https://codesandbox.io/s/vue-template-c2gtb
Click on 'Go to Page with nested router' link
Click on 'commit event', it will show an alert box
Now change the nested route by clicking 'change nested route to reporting'
What is expected?
Route changed to reporting without showing the 'hello' alert box.
What is actually happening?
Its showing the 'hello' alert box again.
You should change your watcher to ignore cases when old value is the same as new value:
watch: {
event: {
handler(newVal,oldVal) {
if(oldVal === newVal) return; // <--- the important part
switch (this.event.id) {
case 'new_requirement': {
alert('hello');
break;
}
default:
}
},
},
},

Aurelia Dialog and Handling Button Events

I have set up the aurelia-dialog plugin. It's working using the example in the GitHub readme, but the documentation doesn't explain anything about how to use it otherwise. I have a simple use case with a list page. I want to click an "add new" button, pop the modal dialog which has it's own VM. The modal contains a simple dropdown list. I need to select an item on the list and make an API call to save the data, but I can't seem to figure out how to wire up my save method with the save button on the dialog.
The method that opens the dialog on my list page (which works just fine):
loadAgencyDialog(id){
this.dialogService.open({ viewModel: AddAgency, model: { id: id }}).then((result) => {
if (!result.wasCancelled) {
console.log('good');
console.log(result.output);
} else {
console.log('bad');
}
});
My modal add-agency.js (VM for the modal, also loads the select list just fine and yes, I have a variable named kase because case is reserved):
import {DialogController} from 'aurelia-dialog';
import {ApiClient} from 'lib/api-client';
import {inject} from 'aurelia-framework';
#inject(DialogController, apiClient)
export class AddAgency {
kase = { id: '' };
constructor(controller, apiClient){
this.controller = controller;
this.agencies = [];
this.apiClient = apiClient;
}
activate(kase){
this.kase = kase;
this.apiClient.get('agencies')
.then(response => response.json())
.then(agencies => this.agencies = agencies.data)
.then(() => console.log(this.agencies)); //these load fine
}
addAgency() {
//Do API call to save the agency here, but how?
}
}
This is part I'm unsure about. In the example, they use controller.ok(theobjectpassedin), which returns a promise. But I don't get where I can call my addAgency method. Any ideas?
It's possible I'm misunderstanding your question, but you should be able to just call addAgency() in your HTML:
<button click.trigger="addAgency()">Add</button>
And then do what you need to do in addAgency(), finishing with a call to this.controller.ok() to wrap up the modal.
As an example, here's my modal's dialog-footer:
<ai-dialog-footer>
<button click.trigger="controller.cancel()">Cancel</button>
<button click.trigger="ok(item)">Save</button>
</ai-dialog-footer>
And in my code:
ok(item) {
this.controller.ok(item);
}
Not too complex. Hope that helps.

jqGrid: different navigator buttons depending on login status

I want to use different navigator buttons in jqGrid depending on login status.
for example: if the user is logged in then add/delete/edit button appeared.
Any ideas?
Thanks in advance.
It is possible to add buttons programmatically using the navButtonAdd method (for the navigation bar) and the toolbarButtonAdd method for the toolbar. For example:
jQuery("#grid").toolbarButtonAdd('#t_meters',{caption:"MyButton",
id: "t_my_button",
title: "Do my button action",
buttonicon: 'ui-icon-edit',
onClickButton:function(){
// Button handle code goes here...
}
});
And:
jQuery("#grid")..navButtonAdd('#pager',{
id: "t_my_button",
title: "Do my button action",
buttonicon: 'ui-icon-edit',
onClickButton:function(){
// Button handle code goes here...
}
});
For more information see the Custom Buttons on the Wiki.
Anyway, once this code is in place, you can detect login status server-side. Then use this knowledge to generate client code that only adds the buttons to your grid if the user is supposed to have access to them.
You can also use for example userdata (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#user_data) to send information about buttons which you need to have in the navigator. userdata should be set by server. Then with respect of:
var navGridParams = jQuery("grid_id").getGridParam('userData');
// var navGridParams = { edit: false, add: false, search: true }
you can get the data set by the server.
Now the typical call like:
jQuery("grid_id").navGrid('#pager', { edit: false, add: false, search: true });
You should place not after creating of jqGrid, but inside of than inside of loadComplete. So the code could looks like following:
var isNavCreated = false;
jQuery('#list').jqGrid({
// ...
loadComplete: function () {
var grid = jQuery("grid_id");
if (isNavCreated === false) {
isNavCreated = true;
var navGridParams = grid.getGridParam('userData');
grid.navGrid('#pager', navGridParams);
}
},
// ...
});
Another option that I see, is to use cookie instead of userdata to send information about navGridParams back to the client.