Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Ext.form.Field.setValue() not fire an event? How to "fix" it?

Why is it that Ext.form.Field's setValue does not fire an event to notify listeners it's value has changed? I know there is the change and select event for combobox but these only fire events on user interaction, what about when another component changes the value of a field? Let me explain by a situation i'm facing atm.

I'm currently working on a reusable fieldset component (lets call it ux.fieldset) with a combobox and another fieldset inside. The inner fieldset should be hidden/shown based on the selected value of the combobox. I've registered a listener on the combobox which listens to the select event and when it fires just evaluates the selected value and show/hides the inner fieldset.

Then I add this ux.fieldset as a component to one of my forms.

Now when I do a loadRecord() on the form I would like the value of the inner combobox be re-evaluated so I can show/hide the inner fieldset of my component. The code that does this evaluation should obviously be in the ux.fieldset since that contains the combobox and since it's reusable it would be wise to put it there (DRY).

Is there a preferred or better way to handle this scenario? I've pasted the code of my ux below in case anyone is confused by my explanation above.

Ext.ux.form.StatusFieldSet = Ext.extend(Ext.form.FieldSet, {
     enablePublishFrom      : false // Wether or not the option to (un)publish on a certain date should be visible, defaults to false
    ,item_store             : false
    ,combo                  : false
    ,date_publish           : false
    ,date_unpublish         : false
    ,helpBox                : {
         xtype              : 'box'
        ,autoEl             : {cn: 'Help text<br />'}
    }
    ,publishData_fieldset   : false
    ,datePickerWidth        : 60 // The width of the datepickers in the subfieldset

    ,initComponent : function(){

        this.item_store = [['online',  _('Gepubliceerd')]]; // Online
        if(this.enablePublishFrom) {this.item_store.push(['pending', _('Publiceer op datum')]);} // Publish on date
        this.item_store.push(['offline', _('Niet gepubliceerd')]); // Offline

        this.combo = new Ext.form.ComboBox({
             name           : 'status'
            ,hideLabel      : true
            ,displayField   : 'txt'
            ,valueField     : 'quicklink'
            ,hiddenName     : 'status'
            ,value          : 'online'
            ,forceSelection : true
            ,allowBlank     : false
            ,editable       : false
            ,triggerAction  : 'all'
            ,mode           : 'local'
            ,store          : new Ext.data.SimpleStore({
                 fields     : [ 'quicklink', 'txt' ]
                ,data       : this.item_store
            })
            ,listeners      : {
                 scope      : this
                ,select     : function(combo, value, index) {   // HERE I would like to add another listener that gets triggered when another value is selected or set through setValue()
                    this.showOnPending(value.data.quicklink);
                }
            }
        });

        this.date_publish = new Ext.form.DateField({
             fieldLabel : _('Publiceer op')
            ,name       : 'publish_date'
            ,format     : 'd-m-Y'
            ,width      : this.datePickerWidth
        });

        this.date_unpublish = new Ext.form.DateField({
             fieldLabel : _('De-publiceer op')
            ,name       : 'unpublish_date'
            ,format     : 'd-m-Y'
            ,width      : this.datePickerWidth
        });

        this.publishData_fieldset = new Ext.form.FieldSet({
             autoHeight         : true
            ,hidden             : true
            ,anchor             : '0'
            ,defaults           : {
                 labelSeparator : ''
                ,anchor         : '0'
            }
            ,items              : [ this.helpBox, this.date_publish, this.date_unpublish ]
        });

        // Config with private config options, not overridable
        var config = {
             items      : [ this.combo, this.publishData_fieldset ]
            ,title      : _('Status')
            ,autoHeight : true
        };

        Ext.apply(this, Ext.apply(this.initialConfig, config));

        Ext.ux.form.StatusFieldSet.superclass.initComponent.call(this, arguments);

    }

    ,showOnPending: function(v) {
        if(v == 'pending'){
            this.publishData_fieldset.show();
        } else {
            this.publishData_fieldset.hide();
        }
    }
});

Ext.reg('statusfieldset', Ext.ux.form.StatusFieldSet);

UPDATE:

I've managed to work it out by overloading the setValue method on the combobox instance. But it's by no means an elegant nor good solution if you ask me.

this.combo.setValue = function(v){
    this.showOnPending(v);
    return Ext.form.ComboBox.superclass.setValue.apply(this.combo, arguments);
}.createDelegate(this);

I would like to get some input from ExtJS veterans, how they would handle it.

like image 600
ChrisR Avatar asked Jan 24 '11 11:01

ChrisR


1 Answers

Yep, setValue doesn't fire any events. I can only speculate as to why. I can tell you that You are stepping on any functionality that Combo adds to setValue with your work around though.

Something like this would be safer.

this.combo.setValue = this.combo.setValue.createSequence(this.showOnPending, this);

There is also some code out there that will 'fix' setValue so it fires an event. I'll try to find it. It adds a second parameter to setValue. You could override Combo.prototype.setValue using Ext.override with it: http://code.extjs.com:8080/ext/ticket/185.

In the end I think creating the sequence is still your safest bet.

like image 157
Hemlock Avatar answered Oct 16 '22 16:10

Hemlock