Aurelia boostrap-multiselect plugin

I am trying to get bootstrap-multiselect to work with Aurelia. got a job more or less, but not sure if this is the best solution or if I may run into problems.

Bootstrap-multiselect is a jquery plugin that turns a regular select (multi) into a drop down list with checkboxes ( http://davidstutz.imtqy.com/bootstrap-multiselect/ )

My first problem is getting it to work with dynamically generated parameters. I decided that using the "rebuild" function of the plugins my parameter array (created as a bindable property) is changed. However, the options for the original hhas selection were not yet created, so I use setTimeout to delay recovery, so Aurelia rebuilt the selection. It feels like a "dirty" solution, and I know little about Aurelia outriza to be sure that it will always work.

The second problem is that the value for the component will not be updated, however, the change method will work. I solved this by issuing a change event (found an example for another plugin that does the same). Works great, the value will be updated, but the change method will fire twice. Not a big problem, but it can be a problem if some change takes a lot of time (for example, getting data from a database, etc.).

Any suggestions for improving the code?

<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'); } } 
+5
source share
1 answer

Your first problem can be solved by pressing $(this.element).find('select').multiselect('rebuild'); on microTaskQueue inside the optionsChanged() handler. Thus, Aurelia will fire this event after providing new parameters.

The second problem is not really a problem. It happens that @bindable properties are unidirectional by default. You must declare the value property as two-way. Then you should update the value inside the multiselect.change event.

Finally, your custom element should look 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'); }); } } } 

Execution example: https://gist.run/?id=60d7435dc1aa66809e4dce68329f4dab

Hope this helps!

+1
source

Source: https://habr.com/ru/post/1263169/


All Articles