2017-01-04 14 views
2

У меня есть пользовательский элемент на основе строки (table-like), который динамически создает свой шаблон на основе атрибута bindable columns. Он составляет шаблон строки в строке и использует ViewCompiler, ViewFactory и Просмотр для визуализации.Aurelia - как регистрировать ресурсы просмотра для ViewCompiler?

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 метод, но не смог заставить его работать. Единственный способ, которым я смог заставить его работать, если я зарегистрирую его по всему миру.

Примечание: этот вопрос фокусируется на регистрации ресурсов просмотра. Динамический рендеринг работает просто отлично

+0

Что я ищу это, например, как должен быть зарегистрирован пользовательский элемент? Я предполагаю, что у него есть строковое имя для разрешения и модель представления, необязательно шаблон – balazska

+0

Не дубликат упомянутого вопроса, динамическое представление/рендеринг работает просто отлично. Однако я хотел бы получить пример того, как должен регистрироваться ресурс вида. – balazska

ответ

0

Я нашел решение diggin в docs + github. Я создал два образца для двух разных подходов:

  1. Создать 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);. Единственное отличие состоит в том, что первое читает название из конвенции или декоратора.

  1. Использовать 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); 
      }); 
    } 
} 
0

Я нашел ваш вопрос, борясь с той же проблемой, но мне кажется, мне удалось заставить его работать с параметром resourcescompile. Вот мои настройки:

Я завернул компиляцию во вспомогательный класс:

@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); 
     // ... 
    } 
} 

UPDATE: До сих пор я не в состоянии звоните registerElement вместо registerValueConverter с желаемым эффектом, поэтому мой ответ, вероятно, еще не очень хороший. Я буду продолжать пытаться ...

+0

Да, ключевым моментом было бы использование 'registerElement'. Я знаю, что 'ViewResources' может быть введен, я уже делаю это (я не думал, что это релевантно, но все равно помещаем его в образец). Но этот 'viewResources' будет содержать только ресурсы (пользовательские элементы, атрибуты, конвертеры, поведение) из внешнего контекста. Мне нужно зарегистрировать элемент вручную, эквивалент '' внутри шаблона представления. – balazska

+0

Я разместил этот вопрос в надежде, что какой-то член Aurelia ответит на него быстро. Но так как этого не произошло, я просто буду копаться в docs/github, чтобы узнать. Надеюсь, я скоро смогу отправить ответ :) – balazska