Динамический шаблон в templatURL в angular2

Я использовал ng-include в angular 1 всякий раз, когда мне приходилось включать динамическую диаграмму на странице.

Теперь, как добиться этого в angular 2. Я попытался найти и найти их:

https://groups.google.com/forum/#!topic/angular/ROkKDHboWoA,

https://github.com/angular/angular/issues/2753

может кто-нибудь объяснить, как это сделать в angular2, поскольку ссылка говорит, что ng-include не указывается из-за некоторых соображений безопасности.

Или по крайней мере, как использовать достоверное свойство templateUrl, чтобы можно было проверять достоверное значение на стороне сервера для обслуживания шаблона...

Ответ 1

И как вы можете видеть в этом issue в репозитории Angular, скорее всего, мы не получим эту директиву. Мы долго обсуждали, нужна ли нам эта директива или нет, и если не предусмотрено, как мы можем реализовать ее самим.

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

@Component({
    selector: 'my-ng-include',
    template: '<div #myNgIncludeContent></div>'
})
export class MyNgInclude implements OnInit {

    @Input('src')
    private templateUrl: string;

    @ViewChild('myNgIncludeContent', { read: ViewContainerRef })
    protected contentTarget: ViewContainerRef;

    constructor(private componentResolver: ComponentResolver) {}

    ngOnInit() {
        var dynamicComponent = this.createContentComponent(this.templateUrl);
        this.componentResolver.resolveComponent(dynamicComponent)
            .then((factory: any) => this.contentTarget.createComponent(factory));
    }

    createContentComponent(templateUrl) {
        @Component({
            selector: 'my-ng-include-content',
            templateUrl: templateUrl,
            directives: FORM_DIRECTIVES,
        })
        class MyNgIncludeContent {}
        return MyNgIncludeContent ;
    }
}

Для демонстрации этого Plunker.

Ответ 2

Фактически angular 2 не показывал это в текущей сборке. Также, как и в добавленных ссылках, я не думаю, что эта функция будет включена.

Можно использовать кусок javascript для динамического добавления шаблона с использованием вызова ajax.

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

Ответ 3

Как @binariedMe точно описывает, ng-include отключен в Angular 2 из-за соображений безопасности. Рекомендуемый метод - использовать пользовательскую директиву с немного более программными накладными расходами.

Кроме того, чтобы подготовить код Angular для 2.0:

myApp.directive('myInclude', function() {
    return {
        templateUrl: 'mytemplate.html'
    };
});

И вместо того, чтобы использовать ng-include для элемента, просто добавьте my-include:

<div my-include></div>

Ответ 4

Как alpha.46 (и с ES6 JS):

В файле импорта родительский, который вы хотели включить:

@Component({
  selector: 'account'
})
@View({
  templateUrl: './folder/containing/template.html'
})

Легко, как это.

Если вы хотите импортировать компонент, это то, что вы делаете в родительском файле:

import ComponentClassName from './folder/with/componentName';

...

@View({
  directives: [ComponentClassName]
})

И внутри импортированного файла дочернего/компонента:

Определите свой ComponentClassName (вы можете добавить templateUrl в @View, как показано вверху).

Не забывайте export default ComponentClassName; в нижней части файла.

В официальных документах Angular 2 не так много примеров, но вы спотыкаетесь через него раз в то время.

Ответ 5

Следуя @binariedMe и этому сообщению в блоге http://blog.lacolaco.net/post/dynamic-component-creation-in-angular-2/, я смог построить решение, которое может сработать для вас. Использование вызова AJAX и динамического создания настраиваемого компонента из возвращаемого содержимого html должно устранить эту проблему при создании новой настраиваемой директивы my-ng-include.

import {
  Component,
  Directive,
  ComponentFactory,
  ComponentMetadata,
  ComponentResolver,
  Input,
  ReflectiveInjector,
  ViewContainerRef
} from '@angular/core';
import { Http } from '@angular/http';

export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise<ComponentFactory<any>> {
    const cmpClass = class DynamicComponent {};
    const decoratedCmp = Component(metadata)(cmpClass);
    return resolver.resolveComponent(decoratedCmp);
}

@Directive({
    selector: 'my-ng-include'
})
export class MyNgInclude {

    @Input() src: string;

    constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver, private http: Http) {
    }

    ngOnChanges() {
      if (!this.src) return;

      this.http.get(this.src).toPromise().then((res) => {
        const metadata = new ComponentMetadata({
            selector: 'dynamic-html',
            template: res.text(),
        });
        createComponentFactory(this.resolver, metadata)
          .then(factory => {
            const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
            this.vcRef.createComponent(factory, 0, injector, []);
          });
      });
    }
}

Просто используйте его следующим образом:

<my-ng-include [src]="someChangingProperty"></my-ng-include>