ExtJS 4: Problems with Message confirmation box on a modal window - extjs

I am currently facing a problem which seems to be a very common one for ExtJS or JavaScript users. I am facing a problem due to the Message Confirmation box's Asynchronous nature. I have tried to find the solution on many forums, but none of the solutions haven't given me a simpler way to deal with the below problem. Or may be I failed to understand that hints that were given.
Below is mycode:
var modalWindow = new Ext.Window({
id: 'modalWindow',
...
...
listeners: {
beforeclose: function ( window, eOpts ){
if ( dirtyCheck() ){
//perform abc()
// and don't close the modal window
return false;
}
else {
//perform xyz()
// close the modal window
return true;
}
},
close: function ( panel, eOpts ){
//will trigger beforeclose event to check if all is well
//refresh screen
}
},
buttons: [{
text: 'Close',
handler: function () {
modalWindow.close() // Same close() method is called when we click on window close ( X symbol ) tool.
}
}]
});
function dirtyCheck(){
// Code to check if dirty records exist
if ( /* Found dirty records */ ){
Ext.MessageBox.confirm('Please Confirm', 'Changes not saved. Do you want to close the window?', function (btn) {
if (btn === 'yes') {
console.log('*** clicked yes ****');
window.close();
}
});
}
}
Case Description: I have a grid and double clicking on a grid row opens a modal window coded above. I make some modifications on the modal window. If the user either clicks on the 'Close' button or the modal window close tool ( X symbol on top-right corner ) or even ESC button, I should prompt a confirmation messsage. If the user clicks on 'Yes', I should close the modal window else leave it open.
I have learnt that clicking on the X ( close tool ) or the ESC button fires a 'close' event which in turn fires 'beforeclose' and waits for true/false to either destroy the modal window or keep it open.
Problem: When the user clicks on X ( close tol ) or the ESC button, and while I debug, I see the control going to beforeclose and then the dirtyCheck() function that I wrote. The dirtyCheck function also displays a Message Confirmation box, but the control doesn't wait for me to click on Yes/No. It returns to beforeclose in the background and then to close. So, by the time user decides to click on either 'Yes' or 'No', ExtJS has decided what to do with the modal window and hence I am losing control on whether to close the modal window or not.
Could anyone please help me on what to do in such a case?

You might need to use window.destroy() to remove it after confirmation, your beforeClose function can be
beforeclose: function(window, eOpts) {
Ext.Msg.confirm('Please Confirm', 'Changes not saved. Do you want to close the window?', function(answer) {
if (answer == "yes") {
window.destroy();
}
});
return false;
}

Pass the window to your check function and close it once user have made a choice.
var modalWindow = new Ext.Window({
id: 'modalWindow',
...
...
listeners: {
beforeclose: function ( window, eOpts ){
dirtyCheck(window);
return false;
},
close: function ( panel, eOpts ){
//will trigger beforeclose event to check if all is well
//refresh screen
}
},
buttons: [{
text: 'Close',
handler: function () {
modalWindow.close() // Same close() method is called when we click on window close ( X symbol ) tool.
}
}]
});
function dirtyCheck(window){
// Code to check if dirty records exist
Ext.MessageBox.confirm('Please Confirm', 'Changes not saved. Do you want to close the window?', function (btn) {
confirmation = true;
if (btn === 'yes') {
console.log('*** clicked yes ****');
window.close();
}
});
}
BTW, you can use your way but then you will need to use native browser dialog, see confirm function http://www.w3schools.com/js/js_popup.asp

Related

how to detach a shortcut command on Qooxdoo?

I have this code:
qx.Class.define('my.Window', {
extend: qx.ui.window.Window,
construct: function(caption, icon) {
this.base(arguments, caption, icon);
this.setLayout(new qx.ui.layout.Basic());
this.__btn = new qx.ui.form.Button('Shortcut Test');
this.__cmd = new qx.ui.command.Command('Alt+T');
this.__cmd.addListener("execute", function() { alert('FOOBAR'); });
this.__btn.setCommand(this.__cmd);
this.add(this.__btn);
},
members: {
__btn: null,
__cmd: null
}
});
qx.Class.define('my.Compo', {
extend: qx.ui.container.Composite,
construct: function() {
this.base(arguments);
this.setLayout(new qx.ui.layout.HBox());
this.__btnShow = new qx.ui.form.Button("Show Window", "icon/22/apps/internet-web-browser.png");
this.__btnDestroy = new qx.ui.form.Button('Destroy window');
this.__btnNull = new qx.ui.form.Button('Null window');
this.__btnDestroy.addListener('execute', function(){
this.__window.destroy();
}, this);
this.__btnNull.addListener('execute', function(){
this.__window = null;
}, this);
this.__btnShow.addListener("execute", function(e){
if(this.__window) {
console.info('Window exist');
this.__window.open();
this.__window.center();
}
else {
console.info('Window do not exist!');
this.__window = new my.Window("Shortcut test window");
this.__window.setWidth(300);
this.__window.setHeight(200);
this.__window.setShowMinimize(false);
this.__window.open();
this.__window.center();
}
}, this);
this.add(this.__btnShow);
this.add(this.__btnDestroy);
this.add(this.__btnNull);
},
members: {
__btnShow: null,
__btnDestroy: null,
__window: null
}
});
var compo = new my.Compo();
this.getRoot().add(compo);
So, if you try "Alt+T" shortcut before clicking "Show Window" button, nothing happen. After show the Window, the shortcut is available and an alert is showed.
Well, the issue to me is the remaining availability of the shortcut in scenarios where that shortcut must do not exist any more:
When the window is close normally.
When Null window button is execute, and after that if you use "Alt+T" then the alert is showed twice, and so on as many time you switch between the Null and Show buttons.
Same behavior as (2) even if destroy() method of window is called explicitly.
On playground if "Run" button is clicked several times, also equal times is showed alert after use the shortcut.
Thanks no all for your time. :)
On Playground
The qx.ui.command.Command wraps the qx.bom.Shortcut that attaches 2 listeners to document element. When you close the window qx.ui.command.Command instance was not set inactive or destroyed. You'll have to handle the window close event properly.
destruct: function()
{
this.__cmd = null;
}
it does not destroy the command. If you try:
qx.core.ObjectRegistry.fromHashCode("the command object hash code").getActive()
You will find that it exists and is active. You forgot to destroy the command calling
this.__cmd.dispose()
Qooxdoo Playground App object registry is not initialized every time someone pushes "Run". So, qooxdoo object's lifetime is bound to page lifetime or a disposal event.

Popup on popup, the popup below disappears

I am using the following listeners on the showwindowpopup to grey out(opaque) the background so that nothing is seen. But when I try to close this window, a confirmation window has to appear to confirm from user, but when this confirmation window appears the showwindowpopup behind it which is behind it gets greyed out as well and is not seen.
show: function(win) {
if (this.modal) {
var dom = Ext.dom.Query.select('.x-mask');
for(var i=0; i<dom.length;i++){
Ext.get(dom[i]).setStyle('opacity',1);
}
}
},
close: function(win) {
if (this.modal) {
var dom = Ext.dom.Query.select('.x-mask');
for(var i=0; i<dom.length;i++){
Ext.get(dom[i]).setStyle('opacity',0);
}
}
}
Can someone tell me how can I resolve this? I want the background to be greyed out except the showwindowpopup and the confirmation window. I want the showwindowpopup to be seen whene the confirmation window is open.
Can you Constrain the "show window popup" to the parent panel?

ExtJS 4.1: Modal Window seems to return control before submitting the window

I wasn't sure how to describe my question in the question title. But here is my problem:
(a) When I double click on a row in an Ext.grid.Panel, I open a modal window with it's relavant details to update the record.
(b) After I make the needed modifications and close the modal window, I want to return to the Grid with the Grid filtered on a certain code i.e selectedSalesOrderNum.
jobSlotsGrid.on('celldblclick', function(tableview, td, cellIndex, record, tr, rowIndex, e, eOpts){
modalStatus = loadWindow();
jobSlotStore.filterBy(function(rec) {
alert('Filtering data');
return rec.get('salesOrderNum') === selectedSalesOrderNum;
});
});
(c) Below is the function, which creates the model window. It also has the call to method submitCreateJobSlotHandler() which basically saves the changes and reloads the original Grid with all the data. ( Hence the necessity to filter it back with a certain code i.e selectedSalesOrderNum ).
function loadWindow()
{
getAllTabsForEditJobSlot();
var createJobSlotWin = new Ext.Window({
id:'salesOrder-win-jobSlot',
applyTo : 'hello-win',
modal : true,
layout : 'fit',
width : 900,
height : 500,
closeAction :'destroy',
plain : true,
model : true,
stateful : false,
title :'Create Job Slot',
items : [editJobSlotInformationPanel],
buttons : [{
text : 'Save',
handler : function(){
submitCreateJobSlotHandler();
//createJobSlotWin.destroy();
}
},{
text : 'Close',
handler : function(){
createJobSlotWin.destroy();
}
}]
});
createJobSlotWin.show();
}
The Issue:
In the first block of code, as soon as the loadWindow method is called, both a modal window is popped up along with the filterBy code getting executed in parallel and showing up the alerts ( 'Filtering data' ). I then enter the data in the modal and save. So, basically, the filtering is not done after the Save/Close on Modal. The code ( if/else ) is immediately reached after loading the modal window. It is as if, the modal window opens and goes to the next line of code while waiting for the user to perform some action on the modal window later.
Hope I am clear on my question. Could anyone please advice how do I handle this?
EDIT:
The more I think about it now, I guess the loadWindow() method just creates the Modal Window as we just have a new Ext.Window() call and doesn't bother about other user actions inside the modal and returns the control. And hence, executes the subsequent filterBy event immediately. In that case, I want to filter the store after I am reloading the store upon the Save in Modal Window. The save on Modal window has this handler code:
function submitCreateJobSlotHandler () {
alert('Into Submit');
var formPanel = Ext.getCmp('salesOrderJobSlotForm');
formPanel.getForm().submit({
url : 'someUrl',
method : 'POST',
success : function() {
alert('Success');
jobSlotStore.load({
scope : this,
url : 'salesOrderJobSlot/listJSON'
});
jobSlotStore.filterBy(function(rec) {
alert(rec.get('salesOrderNum')+"--"+selectedSalesOrderNum)
return rec.get('salesOrderNum') === selectedSalesOrderNum;
});
},
failure : function() {
alert('PSO save failed!');
}
});
}
But the issue here is, the jobSlotStore.load() though gets called, it holds until the filterBy gets executed. Because, I see the alerts coming up one by one and then after all the alerts are done, the store loads. So, the filterBy gets overriden by the 'late' store load.
Any suggestions to deal with the issue in any of the ways?
The store load is asynchronous, you need to wait til it completes before you can filter the data set on the client:
store.on('load', function() {
store.filter();
}, null, {single: true});
store.load();

How to prevent itemclick event on check change in Ext Js Tree

I added two listeners 'check change' and 'item click' in Ext.tree.Panel. But i noticed that,
when ever the check change occurs then it is also triggering item click event also. I wish to prevent this item click event.
listeners : {
checkchange: function(node, checked, eOpts){
alert('this is check change');
},
itemclick : function(obj, record, item, index, e, eOpts){
alert('this is item click');
}
}
This are the listeners in Ext tree. On check change i wish to get 'this is check change' this alert only. How it is possible ?
You can use event getTarget method to check DOM of the checkbox. The complete solution is below:
onItemClick: function( self, record, item, index, eventObj, eOpts ) {
var colIdx = eventObj.getTarget('.x-grid-cell').cellIndex;
if (colIdx===0) { // Apply item event click to the first column only
var node=self.getTreeStore().getNodeById(record.internalId);
if (!eventObj.getTarget('.x-tree-checkbox',1,true)) {
record.set('checked',!record.get('checked'));
this.fireEvent('checkchange', node, record.get('checked'));
}
}
}
Lame solution !
I was able to limit the script only to the 'itemclick'.
Works well in ExtJs 5.1.1 and probably in all versions where css checkbox class name is 'x-tree-checkbox'
listeners : {
itemclick : function(panel, record , item , index, event){
var clazz = '';
if(event.target.classList != null){
clazz = event.target.classList[0];
}
if(clazz != 'x-tree-checkbox'){
...
}
}
}
If you are clicking the checkbox to change its value the itemclick event will always fire before the checkchange event. If you dont wish for anything to happen on the itemclick event, simply dont define it (remove the listener).
Have you tried to implement the 'beforeitemclick' event? it fires when you click the item, and inside this handler you can implement the checkchange.

how to reload gird data after add new data in to the store

I have two grids; I call them child and parent grid. When I add a new row(data) into the parent grid, I want to reload the parent grid. I was trying to edit it using the afteredit function in the code. If I uncomment out line number 2 in the alert, that works fine. But with out the alert, the newly added row is hidden. I don't understand what's going wrong in my code. Please can anyone tell me what to do after I add the new row in to my grid and how to reload the grid immediately?
this my afteredit function
afteredit : function (roweditor, changes, record, rowIndex)
{ //alert('alert me');
if (!roweditor.initialized) {
roweditor.initFields();
}
var fields = roweditor.items.items;
// Disable key fields if its not a new row
Ext.each(fields, function (field, i) {
field.setReadOnly(false);
field.removeClass('x-item-disabled');
});
this.grid.getSelectionModel().selectRow(0);
this.grid.getView().refresh();
},
xt.ux.grid.woerp =
{
configRowEditor:
{
saveText: "Save",
cancelText: "Cancel",
commitChangesText: WOERP.constants.gridCommitChanges,
errorText: 'Errors',
listeners:
{
beforeedit: WOERP.grid.handler.beforeedit,
validateedit: WOERP.grid.handler.validateedit,
canceledit: WOERP.grid.handler.canceledit,
afteredit: WOERP.grid.handler.afteredit,
aftershow: WOERP.grid.handler.aftershow,
move: WOERP.grid.handler.resize,
hide: function (p)
{
var mainBody = this.grid.getView().mainBody;
if (typeof mainBody != 'undefined')
{
var lastRow = Ext.fly(this.grid.getView().getRow(this.grid.getStore().getCount() - 1));
if (lastRow != null)
{
mainBody.setHeight(lastRow.getBottom() - mainBody.getTop(),
{
callback: function ()
{
mainBody.setHeight('auto');
}
});
}
}
},
afterlayout: WOERP.grid.handler.resize
}
},
AFAIK RowEditor is a plugin for GridPanel which changes underlying data which comes from store. Usually updates are also made by store. If you want to know when data is saved, you should attach event handler to store. Example:
grid.getStore().on('save', function(){ [...] });
Finally i found solution. When i add reload function in to the afteredit method that will be hide newly added row. So Grid reload After commit data in to that data grid store work well for me. Anyway thanks lot all the people who try to help
this my code look like
record.commit();
grid.getView().refresh();
I think there exist a Save button after editing grid.
So in the handler of Save you can catch the event
or using
Ext.getCmp('your_saveButtonId').on('click', function(component, e) {
// Here they will be checking for modified records and sending them to backend to save.
// So here also you can catch save event
}

Resources