2017-01-22 42 views
5

我試圖讓bootstrap-multiselect與Aurelia一起工作。已經或多或少地工作了,但不知道這是最好的解決方案,還是我可能遇到麻煩。Aurelia的boostrap-multiselect插件

引導,多選是一個jQuery插件,變成一個正常的選擇(多)到一個下拉與複選框(http://davidstutz.github.io/bootstrap-multiselect/

我的第一個問題是把它與動態創建的選擇工作。當我的選項數組(作爲可綁定屬性創建)發生更改時,我通過使用插件「重建」功能解決了這個問題。然而,原始選擇hhas的選項尚未創建,所以我使用setTimeout來延遲重建,所以Aurelia已經重建了選擇。感覺就像是一個「骯髒」的解決方案,我對Aurelia生命週期知之甚少,以確保它始終有效。

第二個問題是組件的值不會被更新,但是更改方法會觸發。我通過發佈一個更改事件來解決這個問題(找到了一些其他插件的實例)。工作正常,值將會更新,但更改方法會觸發兩次。不是一個大問題,但如果更改花費了一些耗時的工作(例如從數據庫獲取數據等),可能會出現問題。

任何改善代碼的建議?

 <template> 
      <select value.bind="value" multiple="multiple"> 
       <option repeat.for="option of options"Value.bind="option.value">${option.label}</option> 
      </select> 
     </template> 

import {customElement, bindable, inject} from 'aurelia-framework'; 
 
import 'jquery'; 
 
import 'bootstrap'; 
 
import 'davidstutz/bootstrap-multiselect'; 
 

 
@inject(Element) 
 
export class MultiSelect { 
 

 
    @bindable value: any; 
 
    @bindable options: {}; 
 
    @bindable config: {}; 
 

 
    constructor(private element) { 
 
     this.element = element; 
 
    } 
 

 
    optionsChanged(newVal: any, oldVal: any) { 
 
     setTimeout(this.rebuild, 0); 
 
    } 
 

 
    attached() { 
 
     var selElement = $(this.element).find('select'); 
 
     selElement.multiselect(
 
      { 
 
       includeSelectAllOption: true, 
 
       selectAllText: "(All)", 
 
       selectAllNumber: false, 
 
       numberDisplayed: 1, 
 
       buttonWidth: "100%" 
 

 
      }) 
 
      .on('change', (event) => { 
 
       if (event.originalEvent) { return; } 
 
       var notice = new Event('change', { bubbles: true }); 
 
       selElement[0].dispatchEvent(notice); 
 
      }); 
 
    } 
 

 
    detached() { 
 
     $(this.element).find('select').multiselect('destroy'); 
 
    } 
 
    
 
    rebuild =() => { 
 
     $(this.element).find('select').multiselect('rebuild'); 
 
    } 
 
}

+0

我已經有一些與DataTables相同類型的問題,並最終寫我自己的。 Aurelia的綁定是驚人的,但我還沒有學會在DOM更新完成時觸發事件的方式。這就是你想引導你注意的地方 - 如何在正確的時刻運行組件的'rebuild'方法。 – LStarky

回答

1

你的第一個問題可以通過推$(this.element).find('select').multiselect('rebuild');到microTaskQueue中,optionsChanged()處理程序中來解決。這樣,Aurelia將在渲染新選​​項後觸發此事件。

你的第二個問題其實不是問題。發生的事情是@bindable屬性默認是單向的。您應該聲明value屬性爲雙向。然後,您應該更新multiselect.change事件中的value

最後,您的自定義元素應該是這樣的:

import {inject, bindable, bindingMode, TaskQueue} from 'aurelia-framework'; 

@inject(TaskQueue) 
export class MultiselectCustomElement { 

    @bindable options; 
    @bindable({ defaultBindingMode: bindingMode.twoWay }) value = []; 

    constructor(taskQueue) { 
    this.taskQueue = taskQueue; 
    } 

    attached() { 
    $(this.select).multiselect({ 
     onChange: (option, checked) => { 
     if (checked) { 
      this.value.push(option[0].value); 
     } else { 
      let index = this.value.indexOf(option[0].value); 
      this.value.splice(index, 1); 
     } 
     } 
    }); 
    } 

    optionsChanged(newValue, oldValue) { 
    if (oldValue) { 
     this.taskQueue.queueTask(() => { 
     this.value = []; 
     $(this.select).multiselect('rebuild'); 
     }); 
    } 
    } 
} 

運行例如:https://gist.run/?id=60d7435dc1aa66809e4dce68329f4dab

希望這有助於!

+0

謝謝你的建議。對不起,直到現在纔回復你。當你有麻煩去幫助我時,這是非常粗魯的。直到現在,我一直在研究項目的其他部分,所以忘記了這一點,因爲它是一種工作方式。我認爲bindign是默認情況下的兩種方式=是否將模板中的綁定更改爲value.two方式。我會嘗試你的代碼更乾淨。不能在代碼中選擇所選的值,但會嘗試使其工作。 –