2017-01-22 8 views
5

Я пытаюсь получить bootstrap-multiselect для работы с Aurelia. получили работу более или менее, но не уверены, что это лучшее решение или я могу столкнуться с проблемами.плагин boostrap-multiselect в Aurelia

Bootstrap-MultiSelect является JQuery плагин, который превращает обычный выбор (мульти) в раскрывающихся с флажками (http://davidstutz.github.io/bootstrap-multiselect/)

Моя первая проблема заключается, чтобы заставить его работать с динамически создаваемыми вариантов. Я решил, что с помощью функции «rebuild» плагинов изменяется мой массив параметров (созданный как свойство bindable). Однако параметры исходного выбора 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 двухсторонним. Затем вы должны обновить value внутри события multiselect.change.

Наконец, пользовательский элемент должен быть чем-то вроде этого:

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 Например: https://gist.run/?id=60d7435dc1aa66809e4dce68329f4dab

Надеется, что это помогает!

+0

Благодарим вас за предложение. Извините, что не отвечал вам до сих пор. Это очень грубо, когда у меня возникли проблемы, чтобы помочь мне. Я работал над другими частями проекта до сих пор, поэтому забыл об этом, так как это было как-то вроде work.I думал, что bindign был двумя способами по умолчанию = изменил привязку в шаблоне на select, чтобы быть value.two-way. Я попробую ваш код, который будет чище. Не работает с выбором выбранных значений в коде, но будет пытаться заставить это работать. –