我有一个基于行的(类似于表的)自定义元素,它基于可绑定列属性动态地呈现其模板。它以字符串形式组成行模板,并使用ViewCompiler、ViewFactory和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只继承视图模型的父级视图资源。我的问题是:如何能够注册任何额外的视图资源?我知道ViewCompiler的compile方法中的第二个参数,但无法使它工作。如果我在全球注册它,唯一的方法就是让它工作。
注意:这个问题的重点是注册视图资源。动态渲染效果很好。
发布于 2017-05-24 08:08:43
我在docs+github中找到了一个解决方案。我为两种不同的方法创建了两个示例:
HtmlBehaviorResource实例,这是为了注册一个特定的元素。样本(基于: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);。唯一的区别是,首先从约定或装饰者中读取名称。
ViewEngine并导入(a)整个模块。如果导入多个资源,甚至不同类型(属性、元素、转换器等),这更合适。来自不同的文件。示例:
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-16 14:41:20
我在解决同样的问题时发现了您的问题,但我想我成功地使它能够使用compile的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,因此我的答案可能还不是很好。我会继续努力..。
https://stackoverflow.com/questions/41468304
复制相似问题