Dojo Stateful watch method firing before value is actually set
Question
Using Dojo 1.6.1.
Update: Here a jsfiddle http://jsfiddle.net/E4EaM/1/
A form is created with some fields.
this.projectServiceidField = new dijit.form.TextBox({
label: 'idField'
, name: 'project_service_id'
, required: true
, type: 'hidden'
}).placeAt(this.domNode);
this.projectServiceEquipmentSourceAddress = new dijit.form.FilteringSelect({
name: 'source_address_id'
, required: true
, store: model.CustomerAddressesPairsView
, searchAttr: "name"
, style: "width: 40ex;"
});
The application needs to be notified when all the widget values have been set. To do this, a Deferred object is created with a Stateful watch on the widget's 'value property. The Deferred objects are all placed into a DeferredList. Once a widget's value has been initially set, the watch is removed and it's Deferred object resolved.
//loop
w.deferred = new dojo.Deferred();
da.push(w.deferred);
// Watch the widget's value
w.initWatch = w.watch('value', function(property, oldValue, newValue) {
w.initWatch.unwatch();
console.debug(w.name, 'property:', property, 'oldValue:', oldValue,'newValue:', newValue,'w.get(\'value\'):', w.get('value'));
w.deferred.resolve();
});
// Set the widget's value
w.set('value', value);
//endloop
var dl = new dojo.DeferredList(da);
When the DeferredList is resolved, all the widget values should have been set.
dl.then(
function() {
dojo.forEach(da, function(d) {
console.debug(Date.now(), d);
})
console.debug(Date.now(), dl, 'DeferredList resolved -------->', form.getValues());
console.debug(form.getValues());
}
);
But, it doesn't work as expected. Specifically the fields that do xhr requests. Here are the values generated on the 'value' change events.
project_service_id property: value oldValue: newValue: 1025 w.get('value'): 1025
source_address_id property: value oldValue: newValue: 59 w.get('value'):
source_address_id was supposed to have a value 59 but when I w.get('value'), it's not equal to newValue. Shouldn't they be?
How can I determine when a widget's value has been set? Why isn't value == w.get('value') immediately after w.set('value', value)?
If w.set('value', value) is not really setting the value, shouldn't it return a deferred?
Shouldn't watch only fire after the value has been set?
Dojo Versions:
Fails in Dojo 1.6.1. Watch doesn't always fire and w.get('value') != newValue when it does.
Fails less in Dojo 1.7.2. The watch still doesn't always fire but at least w.get('value') == newValue.
La solution
after some discussion with richard on irc, we were able to figure out that there was some nuance between dojox.data.QueryReadStore
and dijit.form.FilteringSelect
that prevented the "value"
watch callback being fired if the store hasn't already done a fetch
. the working solution was to do a fetch
first and then create the widget in the onComplete
callback - see http://jsfiddle.net/neonstalwart/dEC7M/
the relevant part is
customerAddressesPairsView.fetch({
onComplete: function() {
var w = new dijit.form.FilteringSelect({
name: 'source_address_id',
required: true,
store: customerAddressesPairsView,
searchAttr: "name",
style: "width: 40ex;"
}, 'sourceAddress');
var handle = w.watch(function(property, oldValue, newValue) {
console.log(property, oldValue, newValue);
});
w.set("value", value1);
console.debug('Value set to ' + value1);
console.debug('Immediate get returns:', w.get('value'));
console.debug('Direct access returns: ' + w.value);
}
});