如何使用中继器中的手动编译模板?

时间:2018-07-09 03:31:27

标签: aurelia aurelia-framework aurelia-templating

我正在为LOB风格的Aurelia应用构建自定义数据网格框架,并且需要有关如何对主网格元素进行模板化的帮助,以便它可以从子列元素中提取自定义单元格模板以进行渲染。

这是我到目前为止所做的:

grid-example.html

<data-grid items-source.bind="rowItems">                    
    <data-column property-name="Name" t="[displayName]fields_Name">
        <div class="flex -va-middle">
            <div class="user-avatar avatar-square">
                <img
                    if.bind="row.dataItem.avatarUri" 
                    src.bind="row.dataItem.avatarUri" />
            </div>

            <span class="name">${row.dataItem.name}</span>
        </div>
    </data-column>

    <data-column property-name="StatusText" t="[displayName]fields_Status">
        <span class="label ${row.statusClass}">${row.dataItem.statusText}</span>
    </data-column>

    <data-column property-name="Location" t="[displayName]fields_Location">
        <span>${row.dataItem.location}</span>
    </data-column>

    <data-column property-name="DateCreated" t="[displayName]fields_MemberSince">
        <span tool-tip.bind="row.dataItem.dateCreated | dateToString:'long-date-time'">
            ${row.dataItem.dateCreated | dateToString:'short-date'}
        </span>
    </data-column>   
</data-grid>

data-column.ts

import {
    autoinject,
    bindable,
    noView,
    processContent,
    ViewCompiler,
    ViewFactory } from "aurelia-framework";
import { DataGridCustomElement } from "./data-grid";

@autoinject
@noView
@processContent(false)
export class DataColumnCustomElement {
    @bindable
    propertyName: string;

    @bindable
    displayName: string;

    cellTemplate: ViewFactory;

    constructor(private readonly _element: Element,
                private readonly _dataGrid: DataGridCustomElement,
                private readonly _viewCompiler: ViewCompiler) {
        this.cellTemplate = this._viewCompiler.compile(`<template>${this._element.innerHTML}</template>`);
        this._dataGrid.columns.push(this);
    }
}

data-grid.html

<template>
    <div class="table-wrapper -data-list -sticky-header">
        <table class="hover unstriped">
            <tbody>
                <tr class="labels">
                    <th repeat.for="column of columns">
                        <span>${column.displayName}</span>
                    </th>
                </tr>
                <tr repeat.for="row of itemsSource">
                    <td repeat.for="column of columns">
                        <!-- inject view for column.cellTemplate here? -->
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</template>

data-grid.ts

import { autoinject, bindable } from "aurelia-framework";
import { DataColumnCustomElement } from "./data-column";

@autoinject
export class DataGridCustomElement {
    @bindable
    itemsSource: any[] = [];

    columns: DataColumnCustomElement[] = [];

    constructor(private readonly _element: Element) {
    }
}

data-column元素声明一个单元格模板,该模板将手动解析为一个ViewFactory实例-我要坚持的是如何为相应的{{ td模板中的1}}转发器,因此它的行为就像我直接在此处声明模板内容一样。

是否可以使用默认的data-grid语法?还是我需要一个自定义模板控制器来执行此操作,它可以另外接受ViewFactory实例作为范围中的可绑定参数?

如果有更好的方法可以满足此要求,那么我也对此持开放态度。

1 个答案:

答案 0 :(得分:1)

您实际上是在尝试编译+渲染动态html。对于repeat.for或表而言,没有什么特别的,但是取决于您要实现的目标,通常比简单地将HTML通过viewCompiler传递要复杂得多。

您可以在我编写的插件中看到一个示例:https://github.com/aurelia-contrib/aurelia-dynamic-html/

我可能会使用该插件(或者简单地复制并粘贴代码并根据您的需要进行调整/优化),然后将其余代码保持原样,执行以下操作:

data-column.ts

this.cellTemplate = this._element.innerHTML; // just assign the raw html

data-grid.html

<tr repeat.for="row of itemsSource">
    <td repeat.for="column of columns"
        as-element="dynamic-html"
        html.bind="column.cellTemplate"
        context.bind="row[column.propertyName]">
    </td>
</tr>

在任何情况下,如果您仅使用像这样或其他形式的自定义元素,就可以使自己更轻松。制作自己的中继器将非常困难;)