Angular 7 Многоразовые шаблоны ng

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

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

@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

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


person Danyx    schedule 11.03.2020    source источник
comment
Можете ли вы предоставить соответствующий код, который у вас есть в настоящее время - минимум, который потребуется для создания таблицы с использованием шаблона для cellTemplate (очевидно, не с помощью окончательного подхода, который вы хотите использовать).   -  person Kurt Hamilton    schedule 13.03.2020


Ответы (5)


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

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

пример StackBlitz

person adrisons    schedule 16.03.2020
comment
Я использую ng-template, проблема, с которой я сталкиваюсь, заключается не в том, чтобы получить шаблон, который находится в одном компоненте, а в том, чтобы взять шаблон из другого компонента. - person Danyx; 16.03.2020
comment
Ах! Я понимаю. Вы хотите вставить компонент динамически. Возможно, это поможет: angular.io/guide/dynamic-component-loader - person adrisons; 17.03.2020

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

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

person Long Nguyen    schedule 18.03.2020

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

Предлагает большую расширяемость.

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

ComponentFactoryResolver

ViewContainerRef

person Vallarasu SambathKumar    schedule 19.03.2020

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

Способ, которым Angular работает для создания экземпляра компонента, заключается в использовании преобразователя Factory, который создаст новый компонент и 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]
})

Я сделал демонстрацию, чтобы она была более понятной, вы можете узнать больше о динамическом создании компонентов в этом < href="https://medium.com/@lukaonik/how-to-create-dynamic-components-in-angular-a2f449acb987" rel="nofollow noreferrer">статья Луки Оникадзе.

person Enrique Scherer    schedule 19.03.2020

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

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

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

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

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

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

Этого удалось добиться благодаря сообщению пользователя alarm9k.

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

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

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

ПРЕДУПРЕЖДЕНИЕ:

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

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

person Billy Cottrell    schedule 18.03.2020