PDA

View Full Version : [OPEN] Field setValue() firing change event



wsi2
22 Jun 2011, 7:59 AM
REQUIRED INFORMATION


Ext version tested:


Ext 4.0.2



Browser versions tested against:


Chrome 12



Description:


Ext.form.field.Field - Fires change event on call to setValue() even though this event should only be fired on user-initiated change.



Steps to reproduce the problem:


Create a subclass of Ext.form.field.Field.
Add a listener for the field's change event.
Set the field's value using setValue().



The result that was expected:


The handler is not called.



The result that occurs instead:


The handler is called.



Test Case:



var textArea = Ext.create('Ext.form.field.TextArea', {
listeners: {
change: {fn: function() { alert('Change event fired.'); }}
}
});

var button = Ext.create('Ext.Button', {
listeners: {
click: {fn: function() { textArea.setValue('text'); }}
},
text: 'Set Value'
});

Ext.create('Ext.form.Panel', {
items: [textArea],
buttons:
});


[B]HELPFUL INFORMATION

Screenshot or Video:


none



See this URL for live test case: http://

Debugging already done:


I found that Ext.form.field.Field's setValue() calls its checkRange() which fires the change event.



Possible fix:


not provided



Additional CSS used:


only default ext-all.css



Operating System:


Windows 7 Professional

mike.estes
23 Jun 2011, 1:14 PM
thanks for the report, we've just introduced a new bug template that will help us migrate bugs from the forums to our bug tracker. Could you please update your ticket to follow this template (http://www.sencha.com/forum/showthread.php?138165-How-to-report-a-bug) so that we can address it faster?

wsi2
23 Jun 2011, 1:54 PM
Done.

wsi2
24 Jun 2011, 7:24 AM
In case anyone else is finding this bug to be a problem, here is the workaround I am using:



/**
* @private
* Sets the value of a field and surpresses its event.
* This is mostly done to avoid a field's change event from firing unless the user changes the field.
* @param {Mixed} field The field whose value to set.
* @param {Mixed} value The value to set.
*/
__setValue: function(field, value) {
field.suspendEvents(false);
field.setValue(value);
field.resumeEvents();
}

edspencer
6 Sep 2011, 6:00 PM
This one could go either way - why do you think it should only fire for user-initiated events? What if the user was interacting with some other component that then changed the field's value - in that case it wouldn't receive an event either...

christophe.geiser
6 Sep 2011, 10:40 PM
imho, this behavior is clearly not a bug.
The value of a field changes on calling Field.setValue() : change event should fire.
Cheers,
C.

tvanzoelen
6 Sep 2011, 11:35 PM
In my opinion this is not a bug. In ExtJs 3 a change event wasn't fired on setValue. In some cases a TriggerField or Combobox did fire a change event on setValue. In my opninion that was a bug.

I think, if you change a value dynamically with code, it is easy to fire an event programmatically with it.

I think in this stage, something is a bug if a feature is behaving differently from ExtJs 3. If now an event is triggered on setValue, I probably get new migration problems. Please file this as a feature request.
The decision not to fire a change event on setValue() was taken in earlier versions of ExtJs, I think so be it!

wsi2
7 Sep 2011, 7:20 AM
I just reported it as a bug because the behaviour was different than I was used to with ExtJS 3. Maybe you guys are right and this is desired behaviour now.

edspencer
7 Sep 2011, 5:45 PM
I'll mark this one closed, it seems to be doing the right thing already

el_chief
9 Jan 2012, 10:03 AM
I call this one a bug.

1. Every browser javascript implementation on the planet ignore onchange when change is initiated in code. Only fires on user change. It has been this way for decades.

2. If I want to load a model into a form, and then write back to that model when a field changes, I can't, because onchange fires when I load the model into the form...

At least add a property to form field where I can turn off code-initiated onchange events please.

Thanks

hendricd
9 Jan 2012, 3:26 PM
For Ext < 4, the 'change' event was always fired based upon user interaction (usually after blur).

That said, I've traditionally ALWAYS added a new 'valuechange' event to ALL (Ext.*) fields during real-life implementations, so that any time a value changed a relevant event is raised.

The most significant benefit is for loading a model->form with linked combos (and after). This safely isolates and preserves 'user-generated' actions (change event) from systemic/internal field updates and eliminates the need to create arduous custom store.load listeners (which most forget to clean-up/bind/unbind) throughout a solution for data-bound controls.

It's MVController-friendly, and entirely optional!

+10 for 'valuechange' event !

vishalg
27 Apr 2012, 3:09 PM
This to seems to be a legitimate use case. I have cases in our application where I am updating more than one field and I don't want the change event to trigger for each change but only once per operation.

Even Ext has places where it calls setValue and not throw a change event. For example when initializing a field setting initial value.

Anyway I have the following work around.


field.suspendCheckChange++;
field.setValue( newValue );
field.suspendCheckChange--;

ChriZ
5 Jun 2012, 6:04 AM
Hello, (=

i see this also as a bug... on every other framework its possible to fill a form without fireing all change events...
.NET C# Forms as a example...

how can you fill a sencha touch 2 form without fireing all change events and handle a save with the change event on all fields...?

at the moment... its not possible to fill a form without triggering the change events...
how should we do it ? when you say its not a bug? do you have a solution?

thanks for you anwers :)

Greetz ChriZ

EDIT:
if i use my workaround:

Ext.override(Ext.field.Input, {
/**
* @private
* Sets the value of a field and surpresses its event.
* This is mostly done to avoid a field's change event from firing unless the user changes the field.
* @param {Mixed} field The field whose value to set.
* @param {Mixed} value The value to set.
*/
setValue: function(value) {
this.suspendEvents(false);
this.callParent(arguments);
this.resumeEvents();
}
});


Ext.override(Ext.field.Checkbox, {
/**
* @private
* Sets the checked state of a field and surpresses its event.
* This is mostly done to avoid a field's change event from firing unless the user changes the field.
* @param {Mixed} field The field whose value to set.
* @param {Mixed} value The value to set.
*/
setChecked: function(newChecked) {
this.suspendEvents(false);
this.callParent(arguments);
this.resumeEvents();
},
});

the X on the textfield to delete text wont work anymore... also the select from selectboxes...
so this is no solution...

ChriZ
6 Jun 2012, 5:25 AM
after a bit reading and testing i found a good solution for Sencha Touch 2.0.1...

data.form = self.getPropertiesForm();
data.form.getFieldsArray().forEach(function(field) {
field.suspendEvents(false);
});
data.form.setValues(Ext.decode(data.responseText));
data.form.getFieldsArray().forEach(function(field) {
field.resumeEvents();
});

on every code piece where you use setValue or setRecord or loadRecord.

if someone knows a better way please contact me... thanks :)

el_chief
6 Jun 2012, 10:12 AM
When I tried that, it was screwing up combobox loading, but that was a while ago.

What I do now is to set a .loading property on the form, and in the field.change event check if the form is loading and return if it is.

mark.Ma
8 Aug 2012, 10:18 AM
You can initial the combobox 2 way:
1,use value property to initial
2,use store event "load" to initial combobox and you can do more here,the following is my code:


listeners:
{

"load":function(store,records,option)
{
var combo=this.find("name","point")[0];
if(this.data&&this.data.point)
{
Ext.each(records,function(obj,index){

if(obj.get("point")==this.data.point)
{
combo.setValue(obj.get("id"));
combo.fireEvent("change",combo,obj.get("id"),"");
return(false);
}
},this);
}
else
{
combo.setValue("");
combo.fireEvent("change",combo,"","");
}

},
scope:this


}


my sample code have a bit complex ,i compare the text to initial a combobox(generally you just use setValue directly),and i manual Fires a "change" event to load another related combobox.it's flexible.
i hope my sample code can help you.

DerekBrennan20
11 Sep 2012, 2:05 AM
This is absolutely 100% a bug, and an extremely irritating one at that. An event should ONLY be fired on a user interaction. This is the case everywhere else. What's the different here?

JakeLatham
17 Sep 2012, 9:15 AM
I'd agree with the above - at the very least, we need a way to suppress the firing of the event, something like:

field.setValue(value, false);

-Jake

peisenmann
7 Dec 2012, 7:37 AM
This is not a bug, in my humble opinion, but the ability to suppress events is a needed feature, too. I've personally run into both cases with Ext4. One where I wanted to setValue on a combobox and have it fire the events (which it does not do by default, example (http://stackoverflow.com/questions/4781461/why-does-ext-form-field-setvalue-not-fire-an-event-how-to-fix-it)), and one where I wanted to setValue on some textfields and have it not fire the events (like this thread).

I agree with previous posters that setValue(value, suppressEvents [default: false]) seems like the right way to go. By default, changing the value should fire a change event by definition, I believe. However, it should not require extra functions or two extra lines of code per field in order to suppress them.

The fact that this thread has enough people on either side of the fence says to me that it shouldn't require a work around to invoke or suppress the events, rather it should be a simple flag because both use cases are common.

rtirbany
9 Jul 2013, 11:16 AM
How does one go about this? :)
I have a listener defined in my controller code for a checkbox change event, which works as expected (calls my toggleCheckbox() method which updates a store and dataview).

Based on another use case, I need to load and populate this same form/ with the same checkboxes.
How can I call setValue(true) w/o firing the aforementioned change event twice. The form is getting populated load handler on the store.
I've tried:
cbox.suspendEvents(false);
...
(code)
...
resumeEvents();
which does not help. I've also tried fireEvent('change',) and a few other things...no luck. Any thoughts/advice or workarounds?

grizzly21
26 Jul 2013, 3:08 AM
Absolutely right, it's funny that they call it a feature not a bug..either way, it's bad design and is against conventions..

Al Jey
8 Aug 2013, 11:58 PM
This is most certainly not a bug, however it would be nice if setValue would accept a "silent" argument, defaulting to false, so if you were to pass true as a second argument, for example, the event wouldn't get triggered.

grizzly21
9 Aug 2013, 12:24 AM
In the meantime you can use suspendEvents(), resumeEvents()

juz4u2me
16 Sep 2013, 6:23 PM
How about using setRawValue() to overcome this issue instead? I see that it does not trigger the 'change' event.

rt.karthik87
28 Sep 2013, 5:12 AM
wats the final result of this bug... i too dont want to fire change event when i call setValue function.

cepaul
9 Sep 2014, 10:44 AM
+1 for a flag!

This thread shows as still open so I'm replying even though it's 3 years after the OP...
I'm on both sides of the fence on this. Currently, I am using the change event for checks on some fields and for others, I would like to suppress it. A flag argument would be perfect.