2011-01-24 33 views
7

Tại sao bộ setValue của Ext.form.Field không kích hoạt sự kiện để thông báo cho người nghe rằng giá trị của nó đã thay đổi? Tôi biết có sự kiện changeselect cho combobox nhưng những sự kiện cháy duy nhất này trên tương tác của người dùng, điều gì sẽ xảy ra khi một thành phần khác thay đổi giá trị của một trường? Hãy để tôi giải thích bởi một tình huống tôi đang đối mặt với atm.Tại sao Ext.form.Field.setValue() không kích hoạt sự kiện? Làm thế nào để "sửa chữa" nó?

Tôi hiện đang làm việc trên thành phần fieldset có thể tái sử dụng (cho phép gọi nó là ux.fieldset) bằng combobox và một fieldset khác bên trong. Trường dữ liệu bên trong phải được ẩn/hiển thị dựa trên giá trị được chọn của combobox. Tôi đã đăng ký một người nghe trên combobox mà nghe sự kiện select và khi nó cháy chỉ đánh giá giá trị được chọn và hiển thị/ẩn trường nội bộ.

Sau đó, tôi thêm ux.fieldset này làm thành phần vào một trong các biểu mẫu của tôi.

Bây giờ khi tôi thực hiện một loadRecord() trên biểu mẫu, tôi muốn giá trị của combobox bên trong được đánh giá lại để tôi có thể hiển thị/ẩn bộ trường bên trong của thành phần của tôi. Mã thực hiện đánh giá này rõ ràng nên nằm trong ux.fieldset vì có chứa combobox và vì nó có thể tái sử dụng nên nên đặt nó ở đó (DRY).

Có cách nào hay hơn để xử lý trường hợp này? Tôi đã dán mã của ux của tôi dưới đây trong trường hợp bất cứ ai bị nhầm lẫn bởi lời giải thích của tôi ở trên.

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:

tôi đã quản lý để làm việc nó ra do quá tải phương pháp setValue trên dụ combobox. Nhưng nó không có nghĩa là một giải pháp thanh lịch cũng không tốt nếu bạn hỏi tôi.

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

Tôi muốn nhận một số đầu vào từ các cựu chiến binh ExtJS, cách họ xử lý nó.

+0

Mở rộng comboBox để có người nghe đặc biệt cho điều này? (Hoặc có lẽ tôi đọc sai thread? Re-reading .. :) –

+0

Tôi muốn tránh mở rộng Combobox cho vấn đề tầm thường này ... có vẻ như một cái gì đó mà nên được rất nhiều dễ dàng hơn để sửa chữa mà không subclassing một lần nữa – ChrisR

+0

Tôi đã hỏi một câu hỏi và nhận được một phản hồi, mà tôi tin rằng cũng có thể trả lời của bạn: 'Không có sự kiện UI nào được kích hoạt bằng JavaScript. Điều này là để ngăn chặn các vòng lặp vô tận và các tác dụng phụ không mong muốn khác trong khi tương tác với trang theo lập trình. ' http://stackoverflow.com/questions/4591625/what-is-a-good-way-of-filling-a-form-in-extjs-by-code-and-fire-the-events-for- ea –

Trả lời

3

Yep, setValue không kích hoạt bất kỳ sự kiện nào. Tôi chỉ có thể suy đoán là tại sao. Tôi có thể nói với bạn rằng bạn đang bước vào bất kỳ chức năng nào mà Combo thêm vào setValue với công việc của bạn xung quanh.

Điều gì đó như thế này sẽ an toàn hơn.

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

Ngoài ra còn có một số mã ở đó sẽ 'sửa' setValue để nó kích hoạt sự kiện. Tôi sẽ cố gắng tìm nó. Nó thêm tham số thứ hai vào setValue. Bạn có thể ghi đè Combo.prototype.setValue bằng cách sử dụng Ext.override với số điện thoại: http://code.extjs.com:8080/ext/ticket/185.

Cuối cùng, tôi nghĩ việc tạo chuỗi vẫn là đặt cược an toàn nhất của bạn.

+0

Tôi đã thử createInterceptor nhưng chưa thử createSequence ... hãy để tôi thử! Cảm ơn ý tưởng. – ChrisR

+0

Cảm ơn, điều đó hoạt động ... tôi đã quản lý để có được nó để làm việc với createInterceptor quá ... tôi quên gán giá trị trở lại ví dụ combobox ... cảm ơn rất nhiều! – ChrisR

0

Thêm một sự kiện thay đổi phương pháp của combobox setValue là khá dễ dàng sử dụng một lớp override:

Ext.define('<app_name>.override.form.field.ComboBox', { 
    override: 'Ext.form.field.ComboBox', 
    setValue(newValue) { 
     let oldValue = this.getValue(); 
     this.callParent(arguments); 
     this.fireEvent('change', this, newValue, oldValue) 
    } 
} 

Bạn chỉ cần để đảm bảo rằng tập tin có chứa mã này được nạp bởi ứng dụng. Tôi vẫn đang sử dụng Ext 5 vì vậy tôi thêm nó vào mảng yêu cầu của tập tin Application.js của dự án, nhưng tôi tin rằng Ext 6 có một thư mục ghi đè và chỉ cần đặt tệp này ở đó đảm bảo rằng nó được tải.

Các vấn đề liên quan