PDA

View Full Version : Using MessageBox in an Event Handler


walker1c
03-31-2008, 04:43 PM
There's a lengthy thread elsewhere about the necessity of using an event handler to process the result of a MessageBox. The thread basically concludes that the JavaScript environment does not support any kind of blocking call and that anybody who has "grasped the concepts of OO" should not find this a problem.

I assume from this that there is a well-known solution for what must, surely, be a fairly common use case:

The beforeload event handler of a Store returns a boolean value to indicate whether the load should proceed.
This therefore seems a suitable place to check the Store for pending updates and ask the user whether these should be saved first. But the boolean value has to be returned at once, so there is no way to use an asynchronous completion. I've considered returning false to prevent the Store from loading, then initiating the load from the MessageBox event, but this will lose the parameters of the event that underlies the load request.
Perhaps the beforeload event isn't the best place to handle this. But the load is originally triggered by an event so this doesn't really help.In the end I'm forced to use window.confirm, which looks really ugly in the middle of the beautiful Ext interface. Is there a better solution?

Chris

vmorale4
03-31-2008, 05:00 PM
Do you have a link to the other thread you are talking about?

mykes
03-31-2008, 09:39 PM
Am I missing something?


store.is_dirty = false;
store.on('whatever_event_changes_it', function() { store.is_dirty = true; });

store.on('beforeload', function() {
if (store.is_dirty) {
Ext.MessageBox.confirm("store is dirty", "Really discard it?", function(button) {
if (button == "yes") {
store.is_dirty = false;
store.load();
}
});
return false;
}
return true;
}

walker1c
04-01-2008, 04:00 AM
It could well be that it's me that is missing something.

The load operations I'm thinking of are typically triggered by a navigation event, so the store has been asked to load a specific page, or to sort the data. I considered loading the store in the MessageBox event, but I had assumed that these parameters would be lost by just calling store.load(), but I confess I haven't tried it.

The example given by mykes is presumably not intended to be complete, as the store.load() will trigger another beforeload event, and the only way out of the loop is to answer 'no' in the MessageBox. I think a store.rejectChanges() will prevent the store from appearing dirty again.

The thread I referred to is http://extjs.com/forum/showthread.php?t=22517.

evant
04-01-2008, 04:10 AM
It won't trigger another load, he's using a variable inside the store to track the state.


if (store.is_dirty)
{
store.is_dirty = false;
store.load();
}
//store.is_dirty is only set to true in the event handler for whatever triggers the score

mykes
04-01-2008, 09:30 AM
It won't trigger another load, he's using a variable inside the store to track the state.


if (store.is_dirty)
{
store.is_dirty = false;
store.load();
}
//store.is_dirty is only set to true in the event handler for whatever triggers the score


Basically right.

If store.is_dirty is false, in my example, the beforeunload handler returns true - the if clause isn't executed.

The store.load call in beforeunload is only executed if you answer "yes" to the dialog and after it clears the is_dirty flag. So the beforeunload handler will in fact be called a second time, but the second time will do nothing but return true and let the load continue.

walker1c:

You can answer 'yes' or 'no' and the handler returns false stopping the current store.load(). If you answer no, you don't want to trigger another load() so it doesn't. If you answer yes, it does trigger another load() but clears the is_dirty flag to prevent the dialog bit and it returns true to let the load() go on as you'd want.

I ran into a similar kind of thing when toying with an Ext window with an editor in it. If the user clicks the close box or cancel button, you want to warn him to save his work. The above logic worked like a charm.

The obvious flaw is that when Ext 6.9 comes out and adds an important member to store called is_dirty :)

walker1c
04-02-2008, 03:21 AM
Oops - looks like I need to read the code more carefully.

Unless I'm missing something else as well, store.load() alone won't do the trick, as the original call in this case was to load(options). load() will ask the proxy to fetch the whole dataset, which isn't a good idea when it has 50k rows.

Fortunately the options are passed to the beforeload event, so it's simply a matter of passing them on in the MessageBox completion function. Or, rather, it should be simple: I'm using gwt-ext, which for some reason discards the options argument and declares the Java wrapper for load(options) as private, so a certain amount of hacking is required.

Thanks for your help.

Chris