Typescript Aurelia自定义元素是否从函数中冒泡/委派?

Typescript Aurelia自定义元素是否从函数中冒泡/委派?,typescript,events,delegates,aurelia,Typescript,Events,Delegates,Aurelia,我有一个自定义元素,它在跨度中显示一些文本,如果用户决定编辑文本,我将隐藏跨度并显示文本输入。 当用户将焦点放在文本输入上时,我会隐藏输入并使用更新的文本再次显示跨度。 这一切都很好 当我在页面上使用自定义元素时,我需要能够在页面上触发一个函数,从自定义元素获取更新的文本,以更新数据库中的文本 当用户完成编辑文本并重新显示跨度时,我不知道如何弹出该事件,以便调用页面上的函数来保存更改。 如果我使用的是按钮或其他东西,我可以为按钮单击设置代理,但我不知道如何实现这一点,因为我没有使用按钮 希望这有

我有一个自定义元素,它在跨度中显示一些文本,如果用户决定编辑文本,我将隐藏跨度并显示文本输入。 当用户将焦点放在文本输入上时,我会隐藏输入并使用更新的文本再次显示跨度。 这一切都很好

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

当用户完成编辑文本并重新显示跨度时,我不知道如何弹出该事件,以便调用页面上的函数来保存更改。 如果我使用的是按钮或其他东西,我可以为按钮单击设置代理,但我不知道如何实现这一点,因为我没有使用按钮

希望这有意义!提前谢谢

下面是一些精简的代码

自定义元素。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" />
app.html

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

您可以使用来完成此操作。您可以在您的
focusout
上发布事件,并在代码中的其他地方订阅该事件(很可能是某个地方的服务),以更新您的数据库


自定义元素.ts

服务台



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

我看到您尝试绑定函数。调用绑定就这样完成了,没错

向自定义元素添加@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>
如果您想传递参数,您需要稍微不同地在自定义元素中注册onUpdate更改

自定义元素。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();
            });
        });
    }
}
updateText(){
   if(this.onUpdateChanges)
      this.onUpdateChanges({text: what_ever_value_you_want_to_pass});
}
 saveTextFunction(text:string){
      //Do stuff to update/save/persist something
}
app.html

<custom-element title="Default Text" 
        allow-edit-title.bind="true" 
        on-???????.call="saveTextFunction">
</custom-element>
<custom-element title="Default Text" 
    allow-edit-title.bind="true" 
    on-update-changes.call="saveTextFunction(text)">
</custom-element>
Jesse的答案(EventAggregator)是在应用程序中任意位置的两个元素之间传递信息的方法(例如,“冒泡”并不总是有效)

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

在你的情况下,我要做的就是让一个事件发生。您可以通过如下方式使用
CustomEvent
完成此操作:

自定义元素.ts app.html


EventAggregator正是我想要的!我并不完全同意。传递函数并不是传递行为。它更像是子自定义组件在发生特定事件时可以调用的电话号码。事实上,您也在做同样的事情:onFocusOut调用parent。我同意如果组件处于任意位置并且可能无法直接通信,则应使用EventAggregator。或者使用EventAggregator来广播消息。但在这种情况下,自定义组件必须能够与其父组件通信,因此我宁愿使用我的或您的解决方案。但是,最终所有3种解决方案都能起作用。:-)事后看来,这是一个糟糕的措辞选择。考虑语义学:你正在听一个事件,并且你想做一个直接的1-ON映射来进一步传递这个事件。在这种情况下,发送CustomEvent(在我看来)是最“自然”的解决方案。事件将上升到树中的任何级别。当这种1对1映射不太明显时,或者当元素可以通过绑定轻松访问彼此时,函数调用可以是更干净的解决方案。实现相同功能的代码行更少,但更难重构。所以这要视情况而定。你的解决方案确实可以更好。
 saveTextFunction(text:string){
      //Do stuff to update/save/persist something
}
$(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();
});
<custom-element title="Default Text" 
        allow-edit-title.bind="true" 
        input-changed.delegate="saveTextFunction">
</custom-element>