且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Aurelia自定义元素中的2种方式数据绑定-将自定义元素绑定到父视图模型

更新时间:2022-10-20 22:59:57

这里有两个问题:

  1. 由于不区分大小写,您需要对DOM中的所有属性名称进行大小写

    selected-value.bind="property"

    不是

    selectedValue.bind="property"

  2. 您需要双向绑定.使用装饰器创建@bindable时,其中一个参数是BindingMode,可用于设置默认的绑定模式.

    Aurelia设置了一些合理的默认值,例如input value.bind=".."的默认设置是两种方式,无需明确显示

    如果您不想设置默认的绑定模式,则可以通过绑定来明确显示:

    selected-value.two-way="prop"

希望这会有所帮助:)

我认为在回答此问题后,API发生了一些变化.

@bindable装饰器具有以下信号:

bindable({
  name:'myProperty',
  attribute:'my-property',
  changeHandler:'myPropertyChanged',
  defaultBindingMode: bindingMode.oneWay,
  defaultValue: undefined
})

文档中的Aurelia备忘单是检查快速参考的***位置之一:

http://aurelia.io/docs/fundamentals/cheat-sheet

In my application I have made a lot of "services" which I can inject in my viewmodels to save som redundancy and time.

Now I'm looking to take it 1 step further, and make those form elements (select, text, checkboxes - a select dropdown for starters) and turn them into custom elements, injecting the service in only the custom element.

I can get it working to some extent. The custom element (select in this case) is showing when I require it in the "parent" view, however when I change the selected value of the custom select element, it does not bind to the "parent" viewmodel, which is my requirement.

I want to be able to bind my selected value from the custom element to a property on the "parent" viewmodel via the bind attribute in it's template.

I'll update which a little code snippet in a few minutes.

create.js (what I refer to as parent viewmodel)

import {bindable} from 'aurelia-framework';
export class Create{
    heading = 'Create';
    @bindable myCustomElementValue = 'initial value';
}

create.html (parent view)

<template>
    <require from="shared/my-custom-element"></require>
    <my-custom selectedValue.bind="myCustomElementValue"></my-custom>
    <p>The output of ${myCustomElementValue} should ideally be shown and changed here, as the select dropdown changes</p>
</template>

my-custom.js

import { inject, bindable} from 'aurelia-framework';
import MyService from 'my-service';

@inject(MyService )
export class MyCustomCustomElement {
    @bindable selectedValue;

    constructor(myService ) {
        this.myService = myService ;
    }

    selectedValueChanged(value) {
        alert(value);
        this.selectedValue = value;
    }

    async attached() {
        this.allSelectableValues = await this.myService.getAllValues();
    }
}

What happens is initially the create.html view outputs "initial value", and as I change the value of the custom element select, the newly selected value gets alerted out, but it does not update the bound parent variable, which is still just displaying "initial value".

There are a couple of issues here:

  1. You need to kebab-case any property names in the DOM due to case-insensitivity

    selected-value.bind="property"

    not

    selectedValue.bind="property"

  2. You need to bind two-way. When creating a @bindable using the decorator, one of the arguments is BindingMode which you use to set the default binding mode.

    Aurelia sets some sensible defaults, e.g. the default for input value.bind=".." is two way without being explicit

    If you don't want to set a default binding mode, you can just be explicit with your binding:

    selected-value.two-way="prop"

Hope this helps :)

Edit: I think the API changed a little after this answer.

The @bindable decorator has the following sig:

bindable({
  name:'myProperty',
  attribute:'my-property',
  changeHandler:'myPropertyChanged',
  defaultBindingMode: bindingMode.oneWay,
  defaultValue: undefined
})

One of the best places to check for quick reference is the Aurelia cheat-sheet in the docs:

http://aurelia.io/docs/fundamentals/cheat-sheet