2012-09-04 35 views
7

Tôi đang sử dụng ExtJS 4 và tìm cách tôi có thể ẩn giá trị hiện được chọn từ danh sách thả xuống của combo?Hộp kết hợp Extjs: ẩn giá trị đã chọn từ danh sách thả xuống

Vì vậy, thay vì điều này ("Alaska" hiện đang được chọn trong combobox):

default combobox behaviour

Tôi muốn danh sách các giá trị giống như thế này:

enter image description here

Trong trường hợp của tôi combobox là không thể chỉnh sửa (nghĩa là bạn không thể nhập giá trị tùy ý), tôi không nghĩ rằng nó có ý nghĩa nhiều để hiển thị giá trị đã chọn hai lần: một lần trong đặt trường và một lần trong danh sách thả xuống. Tôi đã thấy những gì được chọn, tôi muốn danh sách thả xuống chỉ hiển thị cho tôi các tùy chọn khác mà tôi có thể chọn.

Cho đến nay tôi không thấy cách dễ dàng để thực hiện điều đó. Có lẽ nơi tốt nhất để bắt đầu là lọc cửa hàng combobox nhưng combobox sử dụng bộ lọc riêng của mình cho chức năng tìm kiếm trực tiếp.

Mọi người đều xem vấn đề này? Tôi đang cố gắng làm điều gì đó kỳ lạ? Tôi rất ngạc nhiên khi tôi không thể tìm thấy bất kỳ chủ đề liên quan nào.

+0

Đã hỏi cùng một câu hỏi trên diễn đàn của Sencha: http://www.sencha.com/forum/showthread.php?241063-Combobox-hide-selected-value-from-dropdown-list&p=882210 –

Trả lời

1

tôi đã kết thúc bằng một phiên bản sửa đổi của @ sra vậy lution:

Ext.define('My.ComboBox', { 
    extend: 'Ext.form.field.ComboBox', 

    /** 
    * @cfg {Boolean} hideActive=true 
    * When true, hides the currently selected value from the dropdown list 
    */ 
    hideActive: true, 

    /** 
    * @private {Ext.data.Model[]} selectedRecords 
    * A Array of selected records, used when hideActive is true 
    */ 

    initComponent: function() { 
     this.selectedRecords = []; 

     this.callParent(); 
    }, 


    setValue: function(value, doSelect) { 
     var store = this.store; 

     if(this.hideActive) { 
      store.suspendEvents(false); 
      // write the current selected back to the store (you need to suspend autoSync if active) 
      // do this BEFORE callParent so the currently selected record would be found in the store 
      store.add(this.selectedRecords); 
     } 

     this.callParent(arguments); 

     if(this.hideActive) { 
      // set the selected as new recordlist 
      this.selectedRecords = this.valueModels; 
      // remove the selected from the store 
      store.remove(this.valueModels); 
      store.resumeEvents(); 
      store.fireEvent('refresh', store); 
     } 

     return this; 
    } 

}); 

Các 'trốn' logic là như nhau, duy nhất tôi thực hiện nó trong phương pháp setValue để đảm bảo rằng nó cũng hoạt động khi lập trình thiết lập giá trị kết hợp, trong đó có trường hợp combobox được khởi tạo với một giá trị .

UPD Ngoài ra, trông giống như store.add(this.selectedRecords); phải được gọi là trướcthis.callParent(arguments);, nếu không combobox sẽ hành động kỳ lạ nếu chúng ta cố gắng để thiết lập cùng giá trị gấp đôi (nó chỉ đơn giản là sẽ không tìm thấy hồ sơ hoạt động trong cửa hàng vì chúng tôi đã xóa nó nên nó sẽ được đặt lại thành trống). Tôi tạm dừng các sự kiện của cửa hàng để ngăn chặn một số sự cố do combobox cố gắng đồng bộ hóa với danh sách thả xuống ở giữa các thao tác của tôi với (các) bản ghi đã chọn và kích hoạt sự kiện 'refresh' của cửa hàng theo cách thủ công khi danh sách được cập nhật. Điều này có thể có tác động hiệu suất nhưng cho đến nay tôi không biết một giải pháp tốt hơn.

5

Tôi không nghĩ rằng bạn phải lựa chọn nhiều ở đây ... có lẽ bạn có thể làm một cái gì đó như thế này:

Ext.define('Your.company.Combo', { 
    extend: 'Ext.form.field.ComboBox', 
    alias: 'widget.specialcombo', 

    /** 
    * @cfg {boolean} hideActive 
    * True to hide any selected record. Defaults to <tt>true</tt>. 
    */ 
    hideActive: true, 

    /** 
    * @private {Ext.data.Model[]} hideActive 
    * A Array of selected records. 
    */ 


    initComponent: function() { 
     this.selectedRecords = []; 

     this.callParent(arguments); 

     this.on('select', this.onSelectionChange, this); 
    }, 

    /** 
    * @private onChangeSelection 
    * eventhandler selections 
    */ 
    onSelectionChange: function (me, recs) { 
     if(!me.hideActive) 
      return; 
     // write the current selected back to the store (you need to suspend autoSync if active) 
     me.store.add(me.selectedRecords); 
     // set the selected as new recordlist 
     me.selectedRecords = recs; 
     // remove the selected from the store 
     me.store.remove(recs); 
    } 
}); 

Đó ví dụ là hoàn toàn chưa được kiểm tra. Nhưng khi cửa hàng chủ yếu là ràng buộc với BoundList mà không phải là kết nối trực tiếp với textfield này nên làm việc. Bạn đang làm một loại bộ nhớ đệm ở đây.

+0

Ý tưởng này có vẻ tốt tôi nhưng mã sẽ không hoạt động. 'this.on ('select', function() {this.onSelectionChange();}, this);' nên được thay đổi thành 'this.on ('select', this.onSelectionChange, this);' để làm cho nó hoạt động cũng đúng 'hideActive: false' không có hiệu lực. – pllee

+0

cảm ơn lời khuyên đó. Tôi đã giám sát những thứ này. Sửa chữa là lên – sra

+0

Cảm ơn, điều đó dường như làm các trick! Đã chỉnh sửa mã của bạn một chút và bây giờ nó hoạt động. –

3

tôi đã đưa ra một giải pháp mà trông thậm chí còn đơn giản hơn và một thử nghiệm nhanh chóng cho thấy không có tác dụng phụ:

Chúng ta có thể rời khỏi Combobox luận hoang sơ nhưng chỉ đơn giản là che giấu mục đã chọn thông qua CSS:

.x-boundlist-selected { 
    display: none; 
} 

Và thì đấy, chúng ta không thấy mục được chọn! Không biết như thế nào đáng tin cậy này sẽ là trong mã sản xuất nhưng vẫn đáng xem xét, tôi nghĩ ...


UPDATE. Đây là giải pháp hoàn chỉnh nếu bạn muốn kiểm soát hành vi này qua cấu hình lá cờ của Combobox:

Ext.define('My.ComboBox', { 
    extend: 'Ext.form.field.ComboBox', 

    /** 
    * @cfg {Boolean} hideActive=true 
    * When true, hides the currently selected value from the dropdown list 
    */ 
    hideActive: true, 

    /** 
    * Internal method that creates the BoundList 
    */ 
    createPicker: function() { 
     var picker = this.callParent(arguments); 

     // honor the hideActive flag 
     if(this.hideActive) { 
     picker.addCls('x-boundlist-hideactive'); 
     } 

     return picker; 
    } 
}); 

Một nơi nào đó trong CSS của bạn:

.x-boundlist-hideactive .x-boundlist-selected { 
    display: none; 
} 

CẬP NHẬT 2. Tìm thấy một vấn đề UI với cách tiếp cận của tôi!

Ẩn mục đã chọn từ danh sách thả xuống sẽ giới thiệu một điều hướng để điều hướng bàn phím: mặc dù phần tử được ẩn trực quan, nó vẫn tồn tại và Ext sẽ chọn nó khi bạn bấm phím UP/DOWN. Trực quan có nghĩa là lựa chọn của bạn sẽ biến mất tại một số điểm và bạn sẽ phải nhấn UP/DOWN một lần nữa để đưa nó trở lại thành phần hiển thị tiếp theo.

Cho đến nay tôi không thể tìm thấy bản sửa lỗi dễ dàng cho việc này. Đặt cược tốt nhất của tôi là sửa đổi itemSelector của danh sách bị ràng buộc (là Chế độ xem dữ liệu), đặt nó thành một cái gì đó như .x-boundlist-item:not(.x-boundlist-selected) để phần tử đã chọn không đưa nó vào truy vấn.

Trong khi chọn bản thân công trình, nó không giải quyết được vấn đề vì Xem thực hiện truy vấn chọn này trước bất kỳ lớp học bổ sung (bao gồm các lớp sản phẩm được chọn) được áp dụng cho các mặt hàng (điều này xảy ra trong Ext.view.AbstractView.refresh().

Ngoài ra, giải pháp này gây ra thất lạc của danh sách thả xuống khi nó xuất hiện trên các combobox!

tôi đã có một cảm giác rằng cách tiếp cận của tôi là cách quá dễ dàng để làm việc một cách hoàn hảo :)

+0

Điểm tốt và nhanh hơn tôi đoán. Chưa bao giờ thử điều đó. – sra

+0

Tôi sẽ để lại câu trả lời không được chấp nhận cho bây giờ, tò mò muốn xem liệu có ai khác nghĩ ra những ý tưởng khác không ... –

+0

Điều này hoàn toàn tùy thuộc vào bạn :) Nhưng bạn có thể bỏ chọn câu trả lời sau.Đó chỉ là thông tin – sra

1

ExtJS 3 Tôi đã viết câu trả lời này dựa trên các câu trả lời khác. Công trình tuyệt vời cho tôi, một chút thay đổi từ những gì bạn đang tìm kiếm.

Name.space.name = new Ext.extend(Ext.form.ComboBox, { 
    type: 'all', 
    oldrec: null, 
    store: null, 
    constructor: function (config) { 
     var me = this; 
     if (config.type === 'all') { 
      me.store = AllConditionStore; 
     } else { 
      me.store = ?.?('RuleParameterType'); 
     } 
     config = Ext.apply({ 
      store: me.store, 
      valueField: 'id', 
      hideActive: true, 
      triggerAction: 'all', 
      lazyRender: true, 
      allowBlank: false, 
      mode: 'local', 
      displayField: 'text', 
      listeners: { 
       select: function (me, recs, index) { 
        if (me.oldrec !== null) 
         me.store.add(me.oldrec); 
        me.oldrec = recs; 
        // remove the selected from the store 
        me.store.remove(recs); 
        // redo store 
       } 
      } 
     }, config); 
     ?.?.Parameter.superclass.constructor.call(this, config); 
    } 
}); 
0

Vì vậy, tôi sử dụng @ giải pháp SRA, nhưng với một sự thay đổi nhỏ, để thêm nội dung ở vị trí ngay bên dưới if(!me.hideActive):

if(me.selectedRecords[0]) { 
    me.store.insert(me.selectedRecords[0].index,me.selectedRecords); 
} 

Bằng cách đó bạn chỉ không thêm chúng vào botton. Tôi biết nó là một bài cũ, nhưng tôi hy vọng nó sẽ giúp mọi người tìm kiếm một giải pháp.

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