How to refresh bootstrap-select's options after load data from ajax api

1.3k views Asked by At

I have create aurelia custom attribute code as below

@customAttribute('bt-select')
@inject(Element)
export class BootstrapSelect {
  @bindable val;
  @bindable list;

  constructor(element) {
    this.element = element;

  }

  attached() {
    $(this.element).selectpicker();
  }

  valChanged(newValue, oldValue) {
      $(this.element).selectpicker("val",_.isObject(newValue)?newValue.id:newValue);
  }

  listChanged(newValue, oldValue) {
    setTimeout(()=>{
       $(this.element).selectpicker("refresh");
    },300)
  }

  detached(){
    this.val = null;
    this.list = null;
    $(this.element).selectpicker("destroy");
  }

}

and use it as below

<select value.bind="form.category" data-width="100"
                                bt-select="val.bind:form.category;list.bind:categorys;">
                          <option value="">select:category</option>
                          <option repeat.for="category of categorys"
                                  value="${category.id}">
                            ${category.name}
                          </option>
                        </select>

the select's options tag repeat from class prop categorys,this.categorys loda data from ajax api,it's async step to render select option tag and I have to add setTimeout func in listChanged method to wait aurelia render the select's options tag complete and then force refresh bootstrap-select component

I feel it's not good, but I haven't better way to resolve it, I konw many jQuery plugin should use completed dom element and render them,but in aurelia framework attached() method ,some data load from async api is there have some post-processing methods or event to invoke after async data had bind to dom

1

There are 1 answers

2
Fabio On BEST ANSWER

You can queue a micro-task, ensuring that your function will run after updating the DOM. For example:

//...
import { TaskQueue } from 'aurelia-task-queue';

@inject(Element, TaskQueue)
export class BootstrapSelect {
  //...
  constructor(element, taskQueue) {
    this.element = element;
    this.taskQueue = taskQueue;
  }

  listChanged(newValue, oldValue) {
    // at this point, a micro-task for updating the dom is already queued.
    // now, you should queue a new task that will run after the previous one is completed. 
    this.taskQueue.queueMicroTask(() => {
      $(this.element).selectpicker("refresh");
    });
  }
}

Similar question: @bindable changeHandler fires before bindings are done updating

Hope this helps!