boostrap-multiselect plugin in Aurelia

Asked By: Anonymous

I am trying to get bootstrap-multiselect to work with Aurelia. have got it working more or less but not sure it is the best solution or if I might run into trouble.

Bootstrap-multiselect is a jquery plugin that turns a normal select (multi) into a drop down with checkboxes (http://davidstutz.github.io/bootstrap-multiselect/)

My first problem is to get it working with dynamically created options. I solved that by using the plugins “rebuild” feature when my array of options (created as a bindable property) changes. However the options of the original select hhas then not yet been created so I use setTimeout to delay rebuilding so Aurelia have rebuilt the select. Feels like a “dirty” solution and I know to little about the Aurelia lifecyle to be sure it will always work.

Second problem is that value for component will not be updated, however the change method will fire. I solved this by firing off a change event (found an example for some other plugin that do the same). Works fine, value wiill be updated but the change method will fire twice. Not a big problem but might be a problem if a change does some time consuming work (like getting data from a database etc).

Any suggestions to improve code ?

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

_x000D_

import {customElement, bindable, inject} from 'aurelia-framework';_x000D_
import 'jquery';_x000D_
import 'bootstrap';_x000D_
import 'davidstutz/bootstrap-multiselect';_x000D_
_x000D_
@inject(Element)_x000D_
export class MultiSelect {_x000D_
_x000D_
    @bindable value: any;_x000D_
    @bindable options: {};_x000D_
    @bindable config: {};_x000D_
_x000D_
    constructor(private element) {_x000D_
        this.element = element;_x000D_
    }_x000D_
_x000D_
    optionsChanged(newVal: any, oldVal: any) {_x000D_
        setTimeout(this.rebuild, 0);_x000D_
    }_x000D_
_x000D_
    attached() {_x000D_
        var selElement = $(this.element).find('select');_x000D_
        selElement.multiselect(_x000D_
            {_x000D_
                includeSelectAllOption: true,_x000D_
                selectAllText: "(All)",_x000D_
                selectAllNumber: false,_x000D_
                numberDisplayed: 1,_x000D_
                buttonWidth: "100%"_x000D_
_x000D_
            })_x000D_
           .on('change', (event) => {_x000D_
                if (event.originalEvent) { return; }_x000D_
                var notice = new Event('change', { bubbles: true });_x000D_
                selElement[0].dispatchEvent(notice);_x000D_
            });_x000D_
    }_x000D_
_x000D_
    detached()  {_x000D_
        $(this.element).find('select').multiselect('destroy');_x000D_
    }_x000D_
    _x000D_
    rebuild = () => {_x000D_
        $(this.element).find('select').multiselect('rebuild');_x000D_
    }_x000D_
}

_x000D_

_x000D_

x000D


Solution

Answered By: Anonymous

Your first problem could be solved by pushing the $(this.element).find('select').multiselect('rebuild'); onto the microTaskQueue, inside the optionsChanged() handler. In this way, Aurelia will fire this event after rendering the new options.

Your second problem is not actually a problem. What is happening is that @bindable properties are one-way by default. You should declare the value property as two-way. Then, you should update the value inside the multiselect.change event.

Finally, your custom element should be something like this:

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 example: https://gist.run/?id=60d7435dc1aa66809e4dce68329f4dab

Hope this helps!

techinplanet staff

techinplanet staff


Windows 10 Kaufen Windows 10 Pro Office 2019 Kaufen Office 365 Lizenz Windows 10 Home Lizenz Office 2019 Home Business Kaufen windows office 365 satın al follower kaufen instagram follower kaufen porno