web-dev-qa-db-fra.com

Angular2: Création de composants enfants par programme

Question

Comment créer des composants enfants dans un composant parent et les afficher ensuite dans la vue en utilisant Angular2 ? Comment s'assurer que les injectables sont correctement injectés dans les composants enfants?

Exemple

import {Component, View, bootstrap} from 'angular2/angular2';
import {ChildComponent} from './ChildComponent';

@Component({
    selector: 'parent'
})
@View({
  template: `
    <div>
      <h1>the children:</h1>
      <!-- ??? three child views shall be inserted here ??? -->
    </div>`,
  directives: [ChildComponent]
})
class ParentComponent {

        children: ChildComponent[];

        constructor() {
            // when creating the children, their constructors
            // shall still be called with the injectables.
            // E.g. constructor(childName:string, additionalInjectable:SomeInjectable)
            children.Push(new ChildComponent("Child A"));
            children.Push(new ChildComponent("Child B"));
            children.Push(new ChildComponent("Child C"));
            // How to create the components correctly?
        }
}
bootstrap(ParentComponent);

Modifier

J'ai trouvé le DynamicComponentLoader dans le aperçu de la documentation de l'API . Mais j'obtiens l'erreur suivante en suivant l'exemple: Il n'y a pas de directive de composant dynamique à l'élément 0

37
Waog

Ce n'est généralement pas l'approche que je prendrais. Au lieu de cela, je m'appuierais sur la liaison de données sur un tableau qui rendrait plus de composants enfants lorsque des objets seraient ajoutés au tableau de sauvegarde. Essentiellement des composants enfants encapsulés dans un ng-for

J'ai un exemple similaire dans le sens où il affiche une liste dynamique d'enfants. Ce n'est pas 100% identique, mais le concept est toujours le même:

http://www.syntaxsuccess.com/viewarticle/recursive-treeview-in-angular-2.

18
TGH

Avertissement: DynamicComponentLoader est obsolète en RC.4.

Dans Angular 2.0, la méthode loadIntoLocation de DynamicComponentLoader permet de créer une relation parent-enfant. Cette approche permet de créer de manière dynamique une relation entre deux composants.

Voici l'exemple de code dans lequel le papier est mon parent et le bulletin est mon composant enfant.

paper.component.ts

import {Component,DynamicComponentLoader,ElementRef,Inject,OnInit} from 'angular2/core';
import { BulletinComponent } from './bulletin.component';

@Component({
    selector: 'paper',
    templateUrl: 'app/views/paper.html'

    }
})
export class PaperComponent {
    constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {

    }

    ngOnInit(){
        this.dynamicComponentLoader.loadIntoLocation(BulletinComponent, this.elementRef,'child');

    }
}

bulletin.component.ts

import {Component} from 'angular2/core';

@Component({
    selector: 'bulletin',
    template: '<div>Hi!</div>'
    }
})
export class BulletinComponent {}

paper.html

<div>
    <div #child></div>
</div>

Peu de choses à prendre en charge sont mentionnées dans cette réponse

11
Anshul

Vous devez utiliser ComponentFactoryResolver et ViewElementRef pour ajouter un composant à l'exécution. Jetons un coup d'œil au code ci-dessous.

let factory = this.componentFactoryResolver.resolveComponentFactory(SpreadSheetComponent);
let res = this.viewContainerRef.createComponent(factory);

Placez le code ci-dessus dans votre fonction ngOnInit et remplacez "SpreadSheetComponent" par le nom de votre composant.

J'espère que cela fonctionnera.

6
Shivang Gupta

Ajouter par programme des composants à DOM dans Angular 2/4 app)

Nous devons utiliser la méthode ngAfterContentInit() lifecycle de AfterContentInit. Il est appelé après l'initialisation complète du contenu de la directive.

Dans le parent-component.html, Ajoutez le a div comme ceci:

<div #container> </div>

Le fichier parent-component.ts Ressemble à ceci:



class ParentComponent implements AfterContentInit {

  @ViewChild("container", { read: ViewContainerRef }) divContainer

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  ngAfterContentInit() {
    let childComponentFactory = this.componentFactoryResolver.resolveComponentFactory(childComponent);
    this.divContainer.createComponent(childComponentFactory);
    let childComponentRef = this.divContainer.createComponent(childComponentFactory);
    childComponentRef.instance.someInputValue = "Assigned value";

  }
}

Dans src\app\app.module.ts, Ajoutez l'entrée suivante aux paramètres de la méthode @NgModule():


  entryComponents:[
    childComponent
  ],

Notez que nous n'accédons pas à div#container En utilisant l'approche @ViewChild("container") divContainer. Nous avons besoin de sa référence au lieu de nativeElement. Nous y accéderons comme ViewContainerRef:

@ViewChild("container", {read: ViewContainerRef}) divContainer

Le ViewContainerRef a une méthode appelée createComponent() qui nécessite de passer une fabrique de composants en tant que paramètre. Pour la même chose, nous devons injecter un ComponentFactoryResolver. Il a une méthode qui charge fondamentalement un composant.

2
student

La bonne approche dépend de la situation que vous essayez de résoudre.

Si le nombre d'enfants est inconnu, NgFor est la bonne approche. Comme il est corrigé, comme vous l'avez mentionné, 3 enfants, vous pouvez utiliser le DynamicComponentLoader pour les charger manuellement. Les avantages du chargement manuel sont un meilleur contrôle des éléments et une référence à ceux-ci dans le parent (ce qui peut également être obtenu en utilisant des modèles ...).

Si vous devez renseigner les enfants avec des données, vous pouvez également effectuer cette opération par injection. Le parent se voit injecter un objet de données remplissant les enfants en place ...

Encore une fois, beaucoup d'options. J'ai utilisé 'DynamicComponentLoader' dans mon exemple modal, https://github.com/shlomiassaf/angular2-modal

1
Shlomi Assaf