2017-01-22 15 views
5

Próbuję uzyskać bootstrap-multiselect do pracy z Aurelia. działa to mniej więcej, ale nie jestem pewien, czy jest to najlepsze rozwiązanie, czy może wpadnę w kłopoty.plugin boostrap-multiselect w Aurelia

Bootstrap-multiselect jest plugin jQuery, która zamienia normalny select (multi) do wyboru z rozwijanej (http://davidstutz.github.io/bootstrap-multiselect/)

Mój pierwszy problem to dostać pracy z dynamicznie tworzonych opcji. Rozwiązałem to, używając funkcji "odbuduj" wtyczek, gdy zmienia się moja tablica opcji (utworzona jako właściwość bindable). Jednak opcje oryginalnego select hhas nie zostały jeszcze utworzone, więc używam setTimeout do opóźnienia odbudowy, więc Aurelia przebudowała selekcję. Czuję się jak "brudne" rozwiązanie i niewiele wiem na temat stylu życia Aurelia, aby mieć pewność, że zawsze będzie działać.

Drugi problem polega na tym, że wartość składnika nie zostanie zaktualizowana, jednak metoda zmiany zostanie uruchomiona. Rozwiązałem to przez wystrzelenie zdarzenia zmiany (znalazłem przykład dla innej wtyczki, która robi to samo). Działa dobrze, wartość będzie zaktualizowana, ale metoda zmiany zostanie uruchomiona dwukrotnie. Nie jest to duży problem, ale może stanowić problem, jeśli zmiana zajmuje czasochłonną pracę (np. Pobieranie danych z bazy danych itp.).

Wszelkie sugestie dotyczące ulepszenia kodu?

 <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

Miałem niektóre z tych samych typów problemów z DataTables i skończyłem pisanie własne. Wiązanie Aurelii jest niesamowite, ale nie nauczyłem się jeszcze sposobu wywoływania zdarzenia po zakończeniu aktualizacji DOM. To właśnie tutaj chcesz skupić swoją uwagę - jak uruchomić metodę "przebuduj" komponent w odpowiednim momencie. – LStarky

Odpowiedz

1

Twój pierwszy problem może być rozwiązany poprzez wciśnięcie $(this.element).find('select').multiselect('rebuild'); na microTaskQueue wewnątrz uchwytu optionsChanged(). W ten sposób Aurelia uruchomi to zdarzenie po renderowaniu nowych opcji.

Twój drugi problem nie stanowi problemu. Dzieje się tak, że domyślnie są to obiekty jednokierunkowe. Powinieneś zadeklarować właściwość value jako dwukierunkową. Następnie należy zaktualizować value w wydarzeniu .

Wreszcie niestandardowy element powinien być mniej więcej tak:

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'); 
     }); 
    } 
    } 
} 

Running przykład: https://gist.run/?id=60d7435dc1aa66809e4dce68329f4dab

nadzieję, że to pomaga!

+0

Dziękuję za sugestię. Przepraszam, że nie odpowiadam do tej pory. To bardzo niegrzeczne, gdy miałeś problem, by mi pomóc. Pracowałem nad innymi częściami projektu do tej pory, więc zapomniałem o tym, ponieważ to było trochę pracy. Myślałem, że bindign jest domyślnie dwukierunkowy = Czy zmienił powiązanie w szablonie na wybranym, aby był wartościowy. Dwukierunkowy. Spróbuję twojego kodu, który jest czystszy. Nie działa przy wybieraniu wybranych wartości w kodzie, ale spróbuje to zadziałać. –