web-dev-qa-db-ja.com

Aureliaで、カスタム要素によって呼び出されるように、含まれているビューモデルから関数をバインドできますか?

ユーザー入力を受け取るカスタム要素があり、[保存]ボタンをクリックしたときに、情報を親のビューモデルに渡して、サーバーに送信して次のセクションに移動できるようにします。たとえば、これを単純化するつもりです。

my-element.js

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

@customElement('my-element')
@bindable('save')
export class MyElement { }

my-element.html

<template>
    <button click.delegate="save()">Click this</button>
</template>

parent-view-model.js

export class ParentViewModel {
  parentProperty = 7;
  parentMethod() {
    console.log(`parent property: ${this.parentProperty}`);
  }
}

parent-view-model.html

<template>
    <require from="./my-element"></require>
    <div class="content-panel">
        <my-element save.bind="parentMethod"></my-element>
    </div>
</template>

デモについては、(app.jsとapp.htmlはparent-view-model.jsとparent-view-model.htmlを表します)を参照してください。

https://Gist.run/?id=96b203e9ca03b62dfb202626c2202989

できます!やや。残念ながら、thismy-elementではなくparent-view-modelにバインドされているようです。したがって、この例では、コンソールに出力されるのはparent property: undefinedです。それはうまくいきません。

EventAggregatorを利用して、カスタム要素とビューモデル間の通信を容易にすることができることはわかっていますが、それを支援できる場合は、複雑さが増すことを避けたいと思います。

9
Anj

これには2つのオプションがあります。カスタムイベントを使用してこれを処理することも、Anjが回答で言及したcallバインディングを使用して処理することもできます。どちらを使用するかは、実際のユースケースによって異なります。

カスタム要素が親のメソッドを呼び出すことができるようにしたい場合VMそしてデータoutを渡すカスタム要素の場合、この要点に示すようにカスタムイベントを使用する必要があります: https://Gist.run/?id=ec8b3b11f4aa4232455605e2ce62872c

app.html:

_<template>
    <require from="./my-element"></require>
    <div class="content-panel">
        <my-element save.delegate="parentMethod($event)"></my-element>
    </div>

    parentProperty = '${parentProperty}'
</template>
_

app.js:

_export class App {
  parentProperty = 7;
  parentMethod($event) {
    this.parentProperty = $event.detail;
  }
}
_

my-element.html:

_<template>
    <input type="text" value.bind="eventDetailValue" />
    <button click.delegate="save()">Click this</button>
</template>
_

my-element.js:

_import { inject, customElement, bindable } from 'aurelia-framework';

@customElement('my-element')
@inject(Element)
export class MyElement {
  eventDetailValue = 'Hello';

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

  save() {
    var event = new CustomEvent('save', { 
      detail: this.eventDetailValue,
      bubbles: true
    });

    this.element.dispatchEvent(event);
  }
} 
_

基本的に、カスタムイベントのdetailプロパティに渡す必要のあるデータを添付します。イベントバインディング宣言では、関数にパラメーターとして_$event_を追加してから、イベントハンドラーで$ eventのdetailプロパティを確認します(_$event.detail_を渡すこともできます。あなたが欲しかった)。

カスタム要素が親のメソッドを呼び出すことができるようにしたい場合VMそして親からデータを渡してもらうVM(または別のカスタム要素から)または何か)、次にcallバインディングを使用する必要があります。バインディング宣言(foo.call="myMethod(myProperty)"で指定することにより、メソッドに渡される引数を指定できます。これらの引数は=から取得されます。 VMカスタム要素のVMからではなく、バインディングが宣言されているコンテキスト)。

15
Ashley Grant

Aurelia docsハブを少しトローリングした後、これを解決することができました。関係する可能性のあるすべてのニュアンスはわかりませんが、この簡単な例では、次の簡単な変更を行うことで修正できました。

Parent-view-model.html(またはGist-runの例ではapp.html)で、_save.bind="parentMethod"_をsave.call="parentMethod()"に変更します。

ただし、カスタム要素から親ビューモデルのメソッドにデータを渡す方法はまだわかりません。

これはaureliaのWebサイトからのドキュメントです。

10
Anj