2016-05-21 5 views
2

DynamicComponentLoader устарел. Я пытаюсь создать родительский компонент, который отображает дочерние компоненты внутри родительского компонента на основе массива дочерних компонентов, что означает, что каждый пользователь имеет файл настроек, содержащий дочерние компоненты, которые должны быть в родительском. Сейчас родитель выглядит примерно так:Угловой RC 2 - Динамически визуализировать компоненты из json-файла

import { Component, OnInit, Input, ComponentResolver, ViewContainerRef } from '@angular/core'; 

import { Child1Component } from '../children/child1.component' 
import { Child2Component } from '../children/child2.component' 
import { Child3Component } from '../children/child3.component' 

import { ParentService } from './parent.service' 

@Component({ 
    selector: 'parent', 
    directives: [Child1Component, Child2Component, Child3Component], 
    providers: [ParentService], 
    template: ` 
    <style> 
     .parent{ 
     background-image: linear-gradient(141deg, #8ecb45 0%, #97cd76 71%, #96d885 100%); 
     width: 100%; 
     height: 200px; 
     } 
    </style> 
    <div class="parent"></div> 
    ` 
}) 
export class ParentComponent { 
    constructor(private parentService:ParentService, private children: any, viewContainer: ViewContainerRef, private componentResolver: ComponentResolver) { 

    this.children = parentService.getChildren(); 

    for(var i = 0; i < children.length; i++) { 
     this.componentResolver.resolveComponent(children[i].component) 
     .then(componentFactory => { 
      const ctxInjector = viewContainer.injector; 
      return viewContainer.createComponent(componentFactory, 0, ctxInjector); 
     }) 
    } 

    } 
} 

Прямо сейчас, позвоните службу в конструкторе ParentComponent, кажется, вызывает некоторые вопросы. Но прежде чем я работал над циклом над компонентомResolver, я смог подключить компонент под этим родительским узлом, но не внутри него.

Кто-нибудь знает, как лучше построить динамический родительский компонент? Это управление типом панели инструментов. В большинстве примеров указано, сколько компонентов будет загружено. Это не будет работать для меня. Я видел несколько сообщений о том, как это сделать, но до сих пор я не видел ничего работающего с RC с конфигурационным файлом.

Это ближе к тому, что я пытаюсь сделать: http://plnkr.co/edit/jAmMZKz2VqponmFtPpes?p=preview , но он использует DCL ...

В настоящее время я получаю сообщение об ошибке, что я не понял, при запуске приложения: TypeError: не могу прочитать property 'query' of null

Спасибо за помощь!

Вот ссылка, если вы чувствуете, как загрузив его и придавая ему удар:

https://github.com/weswhite/ng2-layout

EDIT/UPDATE: Это, возможно, придется делать с детьми: любой я инъекцией. Я не думаю, что я делаю, что правильно, все еще полагая, что немного из ...

+0

Вам не нужно перечислять компоненты в 'директив: [...]', когда они только добавляют 'viewContainerRef.createComponent()'. http://stackoverflow.com/questions/36325212/angular-2-dynamic-tabs-with-user-click-chosen-components/36325468#36325468 - это мой ответ на аналогичный вопрос. –

+0

Что такое 'частные дети: какие-нибудь,' должны пройти? –

+0

Я понял, что сейчас частное все не так. У вас есть идея о том, как вводить какой-либо объект, представляющий массив компонентов? Прямо сейчас я пытаюсь сделать что-то большее, как создание дочернего класса и наличие дочернего ресурса: Child [] на компоненте. Не догадались, что все еще – WesW

ответ

2

Вы можете использовать ComponentResolver с дочерним ViewContainerRef для динамического создания компонента и загрузки их в родительский компонент.

@Component({ 
    selector: 'parent', 
    providers: [ParentService], 
    template: ` 
    <style> 
     .parent{ 
     background-image: linear-gradient(141deg, #8ecb45 0%, #97cd76 71%, #96d885 100%); 
     width: 100%; 
     height: 200px; 
     } 
    </style> 
    <div #content></div> 
    ` 
    }) 

export class ParentComponent { 
    @ViewChild('content', { read: ViewContainerRef }) contentContainer: ViewContainerRef; 

    children: Component[]; 

    constructor(
    private parentService:ParentService, 
    private resolver: ComponentResolver) { 
    this.children = parentService.getChildren(); 
    } 

    ngOnInit() { 
    this.children.forEach((component, index) => this.loadComponent(component, index)); 
    } 

    private loadComponent(component: Component, index: number) { 
    return this 
     .resolver 
     .resolveComponent(component) 
     .then(factory => 
     this.contentContainer.createComponent(factory, index, this.contentContainer.injector)) 
    } 
} 

Я также повышен прилагаемую plunker использовать последнюю @angular и ComponentResolver вместо DynamicComponentLoader: Plunker: http://plnkr.co/edit/Z6bXwBcwAnf4DSpNlU8H?p=preview

Использование DCL с loadNextTolocation: http://plnkr.co/edit/NYgJzz9UjrtGsNnO5WXS?p=info

PS: Вы получаете TypeError : Невозможно прочитать запрос свойства «null» из-за того, как вы вводили children, вам нужно указать тип инъекции.

Смотрите также Angular 2 dynamic tabs with user-click chosen components

+1

Выглядит отлично! Я пошел немного по другому пути, но это тоже сработало бы! Мне нравится, как вы следовали моему первоначальному намерению, не добавляя компонент оболочки. – WesW

+0

Можно ли обновить это до RC5, где ComponentResolver больше не используется? Я попробовал себя, и у меня есть «Нет фабрики компонентов, найденной для ...: ошибка в консоли. –

2

Я уверен, что сообщение об ошибке вы упомянули в вашем вопросе вызывается этим параметром

private children: any, 

Угловая не может инъекции зависимостей, где нет конкретного типа, а также нет аннотации @Inject(...).

Update

Полный пример для класса-оболочки, чтобы иметь возможность добавлять динамические компоненты декларативно

@Component({ 
    selector: 'dcl-wrapper', 
    template: `<div #target></div>` 
}) 
export class DclWrapper { 
    @ViewChild('target', {read: ViewContainerRef}) target; 
    @Input() type; 
    cmpRef:ComponentRef; 
    private isViewInitialized:boolean = false; 

    constructor(private resolver: ComponentResolver) {} 

    updateComponent() { 
    if(!this.isViewInitialized) { 
     return; 
    } 
    if(this.cmpRef) { 
     this.cmpRef.destroy(); 
    } 
    this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => { 
     this.cmpRef = this.target.createComponent(factory) 
    }); 
    } 

    ngOnChanges() { 
    this.updateComponent(); 
    } 

    ngAfterViewInit() { 
    this.isViewInitialized = true; 
    this.updateComponent(); 
    } 

    ngOnDestroy() { 
    if(this.cmpRef) { 
     this.cmpRef.destroy(); 
    }  
    } 
} 

От https://stackoverflow.com/a/36325468/217408

Plunker example RC.1

Plunker example beta.17

+0

Это закончилось тем, что работала отлично, но я пошел на ответ телеазиза, потому что он был более строгим с тем, что я думал. Спасибо за все ваши шлемы p в получении меня к решению! – WesW

Смежные вопросы