Manoj Shevate
Manoj Shevate

Reputation: 742

Integrating select2 plugin in aurelia

I'm integrating select2 plugin in aurelia and I'm facing problem while binding a data which I receive from ajax call and takes few seconds after my custom element is rendered.

import 'select2'
import 'select2/css/select2.css!'
import {
    bindable,
    bindingMode,
    customElement,
    inject
} from 'aurelia-framework'
import $ from 'jquery'

@customElement('select2') 
@inject(Element) 
export class CustomSelect {
    @bindable name = null 
    @bindable({ defaultBindingMode: bindingMode.twoWay }) selected = {} 
    @bindable options = [] 
    @bindable labelField = "label"
    @bindable valueField = "value"

    constructor(element) {
        this.element = element
    }

    bind() {
      this.isComplexModel = this.options && this.options.length > 1 && (typeof this.options[0] !== "string" && typeof this.options[0] !== "number")
      this.translateModel()

      this.selectedValue = this.options[0].value
      this.selectedValue = !this.selected ? this.selectedValue : this.selected[this.valueField]
    }

    attached() {
        $(this.element).find('select')
            .val(this.selectedValue)
            .select2()
            .on('change', (event) => {
                if (this.isComplexModel) {
                  this.selected = event.currentTarget.selectedOptions[0].model
                } else {
                  this.selected = event.currentTarget.selectedOptions[0].model.value
                }
                
                let changeEvent

                if (window.CustomEvent) {
                    changeEvent = new CustomEvent('change', {
                        detail: {
                            value: event.target.value
                        },
                        bubbles: true
                    })
                } else {
                    changeEvent = document.createEvent('CustomEvent')
                    changeEvent.initCustomEvent('change', true, true, {
                        detail: {
                            value: event.target.value
                        }
                    })
                }
                $(this.element).val(event.target.value)
                this.element.dispatchEvent(changeEvent)
            })
    }

    translateModel() {
      if (this.isComplexModel) {
        this.options = this.options.map((option) => $.extend(option, {"label": option[this.labelField], "value": option[this.valueField]}))
      } else {
        this.options = this.options.map((option) => $.extend({}, {"label": option, "value": option}))
      }
    }
}
<template>
    <select name.bind="name" id.bind="name">
        <option repeat.for="option of options" value.bind="option.value" model.bind="option">${option.label}</option>
    </select>
</template>

In this code, attached only gets called once (at that point, the options provided is undefined) and I couldn't found any way to update the select2 with the latest data which I gets from the API.

I need your help to make this custom element workable as and when the options changes its state. Thanks in advance!

Upvotes: 2

Views: 1568

Answers (1)

Bj&#248;rn
Bj&#248;rn

Reputation: 1148

I realize that it's a long time since this question was asked, but i have just done an implementation of Select2 v4.0.3 in Aurelia myself. I thought i could share it here with you. It's a bit different approach than you, and it might not be the perfect solution, but you can take a look. Maybe you will get inspired :)

https://github.com/Kla3mus/select24aurelia

Single and multi select modes should work. Select2 is a bit picky when it comes to the values you set, so selected should be an integer array.

It's in typescript, not JavaScript, but it should be fairly easy to modify it to your needs.

Upvotes: 4

Related Questions