为自定义属性

时间:2016-04-15 18:43:45

标签: aurelia aurelia-binding

我想要什么

<div amazingattr.bind="foo">
    ${$someValueFromAmazingattr}
</div>

就像这是如何工作的:

<div repeat.for="bar of bars">
    ${$index}
</div>

我被困的地方

import {customAttribute} from "aurelia-framework";

@customAttribute("amazingattr")
export class AmazingattrCustomAttribute {
    bind(binding, overrideContext) {
        this.binding = binding;
    }

    valueChanged(newValue) {
        this.binding.$someValueFromAmazingattr = newValue;
    }
}

虽然这样做有效,$someValueFromAmazingattr会在自定义属性的元素之外共享,所以这不起作用:

<div amazingattr.bind="foo">
    Foo: ${$someValueFromAmazingattr}
</div>
<div amazingattr.bind="bar">
    Bar: ${$someValueFromAmazingattr}
</div>

&#34; Foo:&#34; &#34; Bar:&#34;显示相同的最后修改值,因此foobar更改,两个绑定都更改为该值。

为什么我需要这个?

我正在研究一个值动画师,所以虽然我不能写这个(因为值转换器无法以这种方式工作):

${foo | animate:500 | numberFormat: "0.0"}

我可以这样写:

<template value-animator="value:foo;duration:500">
    ${$animatedValue | numberFormat: "0.0"}
</template>

我想我需要指示aurelia为自定义属性创建一个新的绑定上下文,但我找不到这样做的方法。我查看了repeat.for的实现,但这很复杂,我可以弄明白。 (也有不同之处在于创建了多个视图,我不需要)

1 个答案:

答案 0 :(得分:1)

经过多个小时的搜索,我来到了aurelia的with自定义元素,并对该解决方案进行了逆向设计。

免责声明:这有效,但我不知道这是否是正确的方法。我确实在嵌入式视图中测试了这个解决方案(if.bind),包括父属性,写了父属性,所有似乎都有效,但是其他一些绑定解决方案似乎也有用。

import {
    BoundViewFactory,
    ViewSlot,
    customAttribute,
    templateController,
    createOverrideContext,
    inject
} from "aurelia-framework";

@customAttribute("amazingattr")
@templateController //This instructs aurelia to give us control over the template inside this element
@inject(BoundViewFactory, ViewSlot) //Get the viewFactory for the underlying view and our viewSlot
export class AmazingattrCustomAttribute {
    constructor(boundViewFactory, viewSlot) {
        this.boundViewFactory = boundViewFactory;
        this.viewSlot = viewSlot;
    }
    bind(binding, overrideContext) {
        const myBindingContext = {
            $someValueFromAmazingattr: this.value //Initial value
        };

        this.overrideContext = createOverrideContext(myBindingContext, overrideContext);

        //Create our view, bind it to our new binding context and add it back to the DOM by using the viewSlot.
        this.view = this.boundViewFactory.create();
        this.view.bind(this.overrideContext.bindingContext, overrideContext);
        this.viewSlot.add(this.view);
    }

    unbind() {
        this.view.unbind(); //Cleanup
    }

    valueChanged(newValue) {
        //`this.overrideContext.bindingContext` is the `myBindingContext` created at bind().
        this.overrideContext.bindingContext.$someValueFromAmazingattr = newValue;
    }
}