双向绑定不适用于 bootstrap-select with aurelia

Two way binding not working on bootstrap-select with aurelia

我已经成功地创建了一个自定义元素来使用 boostrap-select 元素。但是,我可以从主视图(父视图)为它 pass/bind 值,但是当我使用双向绑定时,我无法从元素中获取 selection。

我的自定义元素是:

import {inject, customElement, bindable} from 'aurelia-framework';
import * as selectpicker from 'bootstrap-select'

@customElement('select-picker')
export class BootStrapSelectPicker {
  @bindable selectableValues = null;
  @bindable newValue = null;
  @bindable selectedValue = 10;

 constructor(){
 }


 attached(){
  $('.selectpicker').selectpicker({
       style: 'btn-info',
       size: 4
  });

 $('.selectpicker').on('change', function(){
    var selected = $(this).find("option:selected").val();

     this.selectedValue = selected;
     console.log(this.selectedValue);
  });

   $('.selectpicker').val(this.selectedValue); <-- the selection here is correct
   $('.selectpicker').selectpicker('refresh');

 }
}

对应的视图为:

<template>
  <select class="selectpicker">
    <option repeat.for="p of selectableValues">${p}</option>
  </select>
</template>

我使用自定义元素的包含视图是:

<template>
   <require from="./select-picker"></require>

   <ul class="list-group">
     <li class="list-group-item" repeat.for="p of messageProperties">
     <div if.bind="p.propertyType == 'string'">
       <div class="form-group">
         <label for="ln">Name: ${p.propertyName}</label>
         <input type="text" value.bind="p.propertyValue" class="form-control" id="ln" >
      </div>
    </div>
    <div if.bind="p.propertyType == 'integer'">
        <div class="form-group">
         <label for="ln">Name: ${p.propertyName}</label>
         <input type="text" value.bind="p.selectedValue" class="form-control" id="ln" >
        <select-picker selectable-values.bind="p.selectableValues"
             selected-value.two-way="p.selectedValue"></select-picker>
    </div>
    </div>
  </li>


 </ul>
</template>

我预计 p.selectedValue 会在使用 select 控件生成 selection 后发生变化,如下所示,使用双向命令:

 selected-value.two-way="p.selectedValue"

但是,p.selectedValue 没有改变。

知道为什么这不起作用吗?

原来是一个简单的范围问题:

attached(){
  $('.selectpicker').selectpicker({
       style: 'btn-info',
       size: 4
  });

 $('.selectpicker').on('change', function(){
    var selected = $(this).find("option:selected").val();

     this.selectedValue = selected; // <-- This here doesn't refer to the VM any more
     // if you look at the line above you are wrapping $(this) with jq, this works 
     // because 'this' is now in the scope of the calling element but 
     // doesn't refer to the aurelia viewmodel
     console.log(this.selectedValue);
  });

   $('.selectpicker').val(this.selectedValue); 
   $('.selectpicker').selectpicker('refresh');

 }

简单的修复是:

attached(){

  var self = this; // <--- Create a ref to the VM

$('.selectpicker').selectpicker({
       style: 'btn-info',
       size: 4
  });

 $('.selectpicker').on('change', function(){
    var selected = $(this).find("option:selected").val();
     // Change this to self
     self.selectedValue = selected; // <--- Correct object gets the value now - binding works
     console.log(this.selectedValue);
  });

   $('.selectpicker').val(this.selectedValue); 
   $('.selectpicker').selectpicker('refresh');

 }

我不确定这在 ES6/7 中将如何实际处理 - 我确定我在某处读到过 this 将如何改变,但由于您正在转换为 ES5,这绝对是注意

以下代码对我有用,以防有人遇到同样的问题:

import {inject, customElement, bindable} from 'aurelia-framework';
import 'bootstrap-select'

@customElement('select-picker')
@inject(Element)
export class BootStrapSelectPicker {
    @bindable name: string;
    @bindable selectableValues;
    @bindable selectedValue;

    constructor(private element) {
    }

    attached() {
        var self = this;
        var $: any = jQuery;
        var $elm = $(self.element).find('select');
        if ($elm.length > 0) {
            $elm.selectpicker();
            $elm.on('change', function () {
                self.selectedValue = $(this).find("option:selected").val();
            });
            this.refreshPicker($elm);
        }
    }

    selectedValueChanged(newValue, oldValue) {
        var $: any = jQuery;        
        var $elm = $(this.element).find('select');
        this.refreshPicker($elm);
    }

    private refreshPicker = ($elm) => {        
        $elm.val(this.selectedValue);
        $elm.selectpicker('refresh');        
    }
}