2

バインド可能な列属性に基づいてテンプレートを動的にレンダリングする、行ベース (テーブルのような) カスタム要素があります。行テンプレートを文字列で構成し、ViewCompilerViewFactory、およびViewを使用してレンダリングします。

import {inject} from 'aurelia-dependency-injection';
import {bindable, ViewCompiler, ViewResources} from 'aurelia-templating';

@inject(ViewCompiler, ViewResources)
export class MyDynamicGrid {
    @bindable columns: any[];
    @bindable rows: any[];

    constructor(viewCompiler: ViewCompiler, viewResources: ViewResources) {
        const template = '<template><custom-element></custom-element></template>'; //this is rather complex in practice

        viewResources.registerElement('custom-element', /* HtmlBehaviorResource? */);
        this._viewFactory = viewCompiler.compile(template, viewResources);
    }

    _render() : void {
        const view = this._viewFactory.create(/* some container */);
        view.bind(someContext, someOverrideContext);
        //attach view to the DOM
    }
}

カスタム テンプレートに標準の HTML 要素が含まれるまで、これは問題なく機能します。カスタム要素をテンプレートに配置し始めると、機能しなくなります。HTML は引き続きレンダリングされますが、カスタム要素の動作は Aurelia によって関連付けられていません。

すべてのカスタム要素を使用するには、「登録」する必要があることを認識しています。「通常の登録」は、 を介してビューで<require>、またはビューモデル@viewResourcesで、またはグローバルに登録することで発生します。

ただし、この特定のケースでは、注入されViewCompilerた はビューモデルの親のビュー リソースのみを継承します。私の質問は次のとおりです。追加のビューリソースを登録するにはどうすればよいですか? ViewCompilercompileメソッドの 2 番目のパラメーターは認識していますが、機能させることができませんでした。グローバルに登録する場合、それを機能させることができた唯一の方法です。

注: この質問は、ビュー リソースの登録に焦点を当てています。動的レンダリングは問題なく動作します

4

2 に答える 2

1

docs+github を掘り下げて解決策を見つけました。2 つの異なるアプローチ用に 2 つのサンプルを作成しました。

  1. HtmlBehaviorResourceインスタンスを手動で作成します。これは、特定の要素を 1 つ登録するためです。

サンプル (ベース: https://github.com/aurelia/templating-resources/blob/master/test/repeat-integration.spec.js )

import {CustomElement} from 'my-components/my-custom-element';
import {inject, Container} from 'aurelia-dependency-injection';
import {ViewCompiler, ViewResources} from 'aurelia-templating';
import {metadata} from 'aurelia-metadata';

@inject(ViewCompiler, ViewResources, Container)
export class MyDynamicGrid {

    //bindables and constructor is ommitted

    init(): void {
        const resource: HtmlBehaviorResource = metadata.get(metadata.resource, CustomElement);
        resource.initialize(this._container, CustomElement);
        resource.load(this._container, CustomElement)
            .then(() => {
                resource.register(this._viewResources);

                this._viewFactory = viewCompiler.compile(template, this._viewResources);
            });
    }
}

備考: 行resource.register(this._viewResources);は と同等this._viewResources.registerElement('custom-element', resource);です。唯一の違いは、最初に規約またはデコレーターから名前を読み取ることです。

  1. ViewEngineモジュール全体を使用およびインポートします。これは、異なるタイプ (属性、要素、コンバーターなど) であっても、異なるファイルから複数のリソースをインポートする場合に適しています。

サンプル:

import {CustomElement} from 'my-components/my-custom-element';
import {inject} from 'aurelia-dependency-injection';
import {ViewCompiler, ViewResources, ViewEngine} from 'aurelia-templating';

@inject(ViewCompiler, ViewResources, ViewEngine)
export class MyDynamicGrid {

    //bindables and constructor is ommitted

    init(): void {
        this._viewEngine
            .importViewResources(['my-components/my-custom-element'], [undefined], this._viewResources)
            .then(() => {
                this._viewFactory = viewCompiler.compile(template, this._viewResources);
            });
    }
}
于 2017-05-24T08:08:43.353 に答える
0

同じ問題に苦しんでいるときにあなたの質問を見つけましたが、resourcesパラメータcompile. これが私のセットアップです:

コンパイルをヘルパー クラスにラップしました。

@autoinject
export class ViewFactoryHelper {
    constructor(resources, viewCompiler, container, loader) {
    }

    compileTemplate(html, bindingContext) {
        let viewFactory = this.viewCompiler.compile(html, this.resources);
        let view = viewFactory.create(this.container);
        view.bind(bindingContext);
        return view;
    }
}

そして、クライアントは次のようになります。

@autoinject
export class SomethingToCreateDynamicControls {
    constructor(viewFactoryHelper, myCustomConverter, anotherCustomConverter) {
        viewFactoryHelper.resources.registerValueConverter('myCustomConverter', myCustomConverter);
        viewFactoryHelper.resources.registerValueConverter('anotherCustomConverter', anotherCustomConverter);
    }

    makeControl(model) {
        let html = '...'; // HTML that uses those converters in normal way
        let compiledTemplate = this.viewFactoryHelper.compileTemplate(html, model);
        // ...
    }
}

registerElement更新:これまでのところ、望ましい効果ではなく呼び出すことができないregisterValueConverterため、私の答えはおそらくまだ良いものではありません。がんばります...

于 2017-05-16T14:41:20.200 に答える