Aurelia自定义元素冒泡/委托功能?

时间:2018-06-06 12:38:44

标签: typescript events delegates aurelia

我有一个自定义元素,在一个范围内显示一些文本,如果用户决定编辑文本,我会隐藏范围并显示文本输入。 当用户聚焦文本输入时,我隐藏输入并使用更新的文本再次显示范围。 这一切都很有效。

当我在页面上使用自定义元素时,我需要能够在页面上触发一个函数,从自定义元素中获取更新的文本以更新数据库中的文本。

当用户完成对文本的编辑并重新显示跨度时,我不知道如何冒出该事件,因此我可以调用页面上的函数来保存更改。 如果我使用按钮或其他东西,我可以设置按钮单击的委托,但不知道如何完成此操作,因为我没有使用按钮。

希望这是有道理的!提前谢谢!

以下是一些精简代码。

自定义-element.html:

<i if.bind="icon" class="${icon}"></i><span if.bind="!(allowEditTitle && isEditingTitle)" maxlength>${title}</span>
<input ref="titleInputEditor" type="text" value.bind="title" if.bind="allowEditTitle && isEditingTitle" maxlength="100" />

自定义-element.ts

@bindable title: string;
@bindable allowEditTitle: boolean = false;
isEditingTitle: boolean = false;

toggleEditTitle() {
    let me = this;
    if (this.allowEditTitle === true) {
        this.isEditingTitle = !this.isEditingTitle;
    }
    if (this.isEditingTitle == true) {
        window.setTimeout(function () {
            $(me.titleInputEditor).focus();
            $(me.titleInputEditor).select();
            $(window).one('click', function () {
                if (me.isEditingTitle == true) {
                    me.toggleEditTitle();
                } 
            });
            $(me.titleInputEditor).one('click', function (e) {
                e.stopPropagation();
            });
            $(me.titleInputEditor).one('focusout', function () {
                me.toggleEditTitle();
            });
        });
    }
}

app.html

<custom-element title="Default Text" 
        allow-edit-title.bind="true" 
        on-???????.call="saveTextFunction">
</custom-element>

3 个答案:

答案 0 :(得分:1)

您可以使用aurelia-event-aggregator来完成此操作。您可以在focusout上发布活动,并在您的代码中的其他位置订阅该活动(很可能是某个地方的服务),这将更新您的数据库。

定制element.ts

import { autoinject, EventAggregator } from "aurelia-framework";

@autoinject
export class CustomElement {
  constructor(private ea: EventAggregator)


...

        $(me.titleInputEditor).one('focusout', function () {
            me.ea.publish('input-changed', me.title);
            me.toggleEditTitle();
        });
...
}

service.ts

import { autoinject, EventAggregator } from "aurelia-framework";

@autoinject
export class Service {
  constructor(private ea: EventAggregator)

  public attached() {
    this.ea.subscribe('input-changed', (value) => {
       // update database using value
    });
  }
}

有关事件聚合器的更多文档,请参阅here

答案 1 :(得分:1)

从我看到你尝试绑定一个函数。这是通过.call绑定完成的,这是正确的。

将@bindable属性添加到自定义元素,并从适当的位置

调用它
@binable onUpdateChanges: Function;
updateText(){
   if(this.onUpdateChanges)
      this.onUpdateChanges();
}
app.html中的

将其绑定为:

<custom-element title="Default Text" 
    allow-edit-title.bind="true" 
    on-update-changes.call="saveTextFunction()">
</custom-element>
在app.ts中的

添加saveTextFunction

saveTextFunction(){
      //Do stuff to update/save/persist something
}

如果你想传递args,你需要在custom元素中注册onUpdateChanges略有不同

自定义-element.ts

updateText(){
   if(this.onUpdateChanges)
      this.onUpdateChanges({text: what_ever_value_you_want_to_pass});
}

<强> app.html

<custom-element title="Default Text" 
    allow-edit-title.bind="true" 
    on-update-changes.call="saveTextFunction(text)">
</custom-element>

<强> app.ts

 saveTextFunction(text:string){
      //Do stuff to update/save/persist something
}

答案 2 :(得分:1)

如果您需要在位于应用中任意位置的两个元素之间传递信息,那么Jesse的回答(EventAggregator)就是您的选择(例如&#34;冒泡&#34;赢得&#39;总是有效)

Schadensbegrenzer的回答也适用于您的特定情况,但我个人认为通过可绑定传递函数更多是为了将行为动态传递给自定义元素,而不是跨元素通信。

我在你的案件中做的事实上是让事件冒出来。您可以使用CustomEvent这样完成此操作:

定制element.ts

$(me.titleInputEditor).one('focusout', function () {
    // it'd be slightly cleaner to inject `Element` in your CustomElement
    // and dispatch this event on that element instead
    me.titleInputEditor.dispatchEvent(new CustomEvent('input-changed', {
        detail: me, // if you want to pass this CustomElement instance up to the listener
        bubbles: true
    }));
    me.toggleEditTitle();
});

app.html

<custom-element title="Default Text" 
        allow-edit-title.bind="true" 
        input-changed.delegate="saveTextFunction">
</custom-element>