Angular 7 Многоразовые нг-шаблоны - PullRequest
0 голосов
/ 11 марта 2020

В настоящее время я создаю повторно используемый компонент-оболочку ngx-datatable, который будет использоваться в моем приложении, так как каждая таблица отличается, мне потребуется несколько шаблонов ng для удовлетворения потребностей каждого компонента.

Идея, над которой я работал, заключалась в создании компонента SharedTemplates, который содержал бы несколько шаблонов ng и предоставлял их, просто имея их в качестве общедоступных c свойств, таких как:

@ViewChild("yesNoTemplate") public yesNoTemplate: TemplateRef<any>;

Чтобы я мог использовать их позже как:

tableComponents: TableComponents = new TableComponents();

     `{
        name: 'Aprobado',
        prop: 'aprobado',
        cellTemplate: this.tableComponents.yesNoTemplate
      }`

Однако это, похоже, не работает, tableComponents не имеет никаких свойств, я полагаю, потому что он не отображается (?).

Использование самого компонента в качестве шаблона не работает, так как я получаю сообщение об ошибке:

TypeError: templateRef.createEmbeddedView is not a function

Как можно сохранить эти шаблоны для повторного использования в количество раз?

Ответы [ 5 ]

0 голосов
/ 20 марта 2020

То, что вы пытаетесь сделать, это создавать компоненты программно, а затем обращаться к их методам и свойствам.

Способ, которым Angular работает для создания экземпляра компонента, заключается в использовании Factory resolver , который создаст новый компонент, и ViewContainerRef , где компонент будет быть прикрепленным и оказанным.

Сначала создайте директиву, которая будет служить ViewContainerRef для одной из ваших таблиц, которая будет визуализировать компонент (который, я полагаю, вам не хватает прямо сейчас) и позволит вам получить доступ к его методам и свойствам.

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appTable]'
})
export class TableDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

Теперь вы можете добавить его в тег ng-template и визуализировать компонент внутри, используя FactoryResolver:


import { Component, ComponentFactoryResolver, ViewChild, OnInit, ComponentRef } from '@angular/core';
import { TableComponent } from './table/table.component';
import { TableDirective } from './table.directive';

@Component({
  selector: 'app-root',
  template: `
  <ng-template appTable></ng-template>
  `,
})
export class AppComponent implements OnInit {

  @ViewChild(TableDirective) tableHost: TableDirective;
  tableComponent: ComponentRef<TableComponent>;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {

  }

    ngOnInit() {

    // TableComponents = new TableComponents();  wrong way!

    /**
    * creating the component factory resolver
    */
    const tableFactory = this.componentFactoryResolver.resolveComponentFactory(TableComponent);
    const viewContainerRef = this.tableHost.viewContainerRef;

    /**
     * clearing just in case something else was rendered before
     */
    viewContainerRef.clear();

    /**
     * now you will be able to access the methods and properties of your component after this
     */
    this.tableComponent = viewContainerRef.createComponent(tableFactory);
  }
}

Наконец, поскольку компонент визуализируется программно, вам нужно добавить его в Массив entryComponents в вашем модуле:

@NgModule({
  declarations: [
    AppComponent,
    TableComponent,
    TableDirective
  ],
  imports: [
    BrowserModule
  ],
  entryComponents: [TableComponent],
  providers: [],
  bootstrap: [AppComponent]
})

Я сделал демоверсию , так что более понятно, вы можете прочитать больше о динамическом создании компонентов в этой статье Луки Оникадзе .

0 голосов
/ 19 марта 2020

Рекомендовать создавать компоненты для каждого необходимого шаблона, а затем разрешать их с помощью ComponentFactoryResolver и подключать к компоненту хоста.

Обеспечивает большую расширяемость.

let type = YesNoComponent;
let factory = cfr.resolveComponentFactory(type);
let instance = host.viewContainerRef.createComponent(factory);

ComponentFactoryResolver

ViewContainerRef

0 голосов
/ 18 марта 2020

Я не знаю, какую angular версию вы используете, но у меня была похожая проблема.

В моем случае я использую Angular 9, и я пытался создать компонент где должен быть загружен шаблон, в котором содержатся html, но также и строки интерполяции "{{}}", и стили должны также применяться к нему. Таким образом, шаблон и стиль были получены с сервера.

Во время моего квеста я также пытался задать этот вопрос по stackoverflow: Динамически внедрить HTML и CSS по запросу .

В какой-то момент я начал задавать вопросы в сообществах программистов на Discord, там кто-то дал мне ссылку на github.

Благодаря полученной ссылке я смог добиться того, что мне нужно :

"Загрузка шаблонов на лету на основе запроса."

Это было достигнуто благодаря сообщению alarm9k .

Если это не было ' Что касается этого поста, я, вероятно, сейчас был бы в той же ситуации, что и вы.

Я надеюсь, что это именно то, что вам нужно.

Да, и для построения таблиц (с сортировкой, фильтрацией , пейджинг, ... и т. д. c.) Я использовал Система данных Clarity Design System , не знаю, интересно ли это в вашем случае.

ВНИМАНИЕ:

Я должен упомянуть, что это имеет 1 плохой эффект. Вы не можете построить проект в производственном режиме, так как он не будет содержать компилятор angular, который необходим для этого решения. Я пытаюсь решить эту проблему самостоятельно, в основном потому, что размер приложения резко увеличивается (в моем случае с 2 МБ до 40-45 МБ).

Использование AOT и JIT в производстве в Angular 9 приложение

0 голосов
/ 18 марта 2020

Вы должны создать экземпляр компонента SharedTemplates на уровне root, а затем сохранить все экземпляры ng-шаблона в общей службе.

Вот моя демонстрация на StackBlitz: https://stackblitz.com/edit/angular-s5ffjr

0 голосов
/ 16 марта 2020

Эта ошибка может быть вызвана использованием устаревших template.

. Поэтому вы должны использовать ng-template вместо template: https://angular.io/guide/angular-compiler-options#enablelegacytemplate

Пример StackBlitz

...