Comment puis-je utiliser/créer un modèle dynamique pour la compilation dynamique de la Composante Angulaire 2.0?
Je veux dynamiquement créer modèle. Cela devrait être utilisé pour construire un ComponentType
à Runtime et place (même remplacer) quelque part à l'intérieur du Composant d'hébergement.
Jusqu'à ce que RC4 j'ai été en utilisant ComponentResolver
, mais avec RC5 je reçois un message:
ComponentResolver
est déconseillé pour la compilation dynamique. UtilisationComponentFactoryResolver
avec@NgModule/@Component.entryComponents
ou ANALYZE_FOR_ENTRY_COMPONENTS fournisseur de la place. Pour l'exécution de la compilation seulement, vous pouvez également utiliserCompiler.compileComponentSync/Async
.
J'ai trouvé ceci (officiel angular2) document
Angulaire 2 Dynamique Synchrone À La Création De Composant
Et comprends que je peux utiliser
- Genre de dynamique
ngIf
avecComponentFactoryResolver
. Si je vais passer composants connus dans l'organisation de l'un à l'intérieur de@Component({entryComponents: [comp1, comp2], ...})
- je peux l'utiliser.resolveComponentFactory(componentToRender);
- Réel d'exécution de la compilation, avec
Compiler
...
Mais la question est de savoir comment l'utiliser Compiler
? La Note ci-dessus, dit que je devrais l'appeler: Compiler.compileComponentSync/Async
- oui, comment?
Par exemple. Je veux créer (en fonction de la configuration de conditions) ce genre de modèle, pour un type de paramètres
<form>
<string-editor
[propertyName]="'code'"
[entity]="entity"
></string-editor>
<string-editor
[propertyName]="'description'"
[entity]="entity"
></string-editor>
...
et dans un autre cas celle-ci (string-editor
est remplacé par text-editor
)
<form>
<text-editor
[propertyName]="'code'"
[entity]="entity"
></text-editor>
...
Et ainsi de suite (autre numéro/date de référence/editors
par types de propriété, ignoré certaines propriétés pour certains utilisateurs...). I. e. ceci est un exemple, configuration réelle pourrait générer beaucoup plus différents et des modèles complexes.
La modèle est en train de changer, donc je ne peux pas utiliser ComponentFactoryResolver
et passer existants... j'ai besoin de solution avec la Compiler
AOT et JitCompiler (ancien RuntimeCompiler)
Vous souhaitez utiliser cette fonctionnalité avec AOT (avance de temps de compilation)? Êtes-vous:
D'erreur: Erreur rencontrée lors de la résolution des valeurs de symbole de manière statique. Les appels de fonction ne sont pas pris en charge. Envisager de remplacer la fonction ou lambda avec une référence à une fonction exportée (position 65:17 dans l'original .fichier ts), la résolution de symbole COMPILER_PROVIDERS dans .../node_modules/@angular/compiler/src/compiler.d.ts,
S'il vous plaît, laissez votre commentaire, vote ici:
Pourrait/serait/sera le code à l'aide COMPILER_PROVIDERS être pris en charge par AOT?
- Étant donné que la solution que j'ai trouvé était tellement agréable que je veux tout le monde à trouver cette question pour avoir un coup d'oeil à ma réponse, qui est très loin vers le bas tout en bas pour le moment. 🙂
- L'article Voici ce que vous devez savoir à propos de la dynamique des composants Angulaire a bonne explication de la dynamique des composants.
- Voici le problème avec chaque réponse là-bas et ce que
$compile
pourraient réellement faire que ces méthodes ne peuvent pas, je suis en création d'une application où j'ai juste envie de compiler le code HTML comme il arrive par une 3ème partie de la page et les appels ajax. Je ne peux pas supprimer le code HTML de la page et de le placer dans mon propre modèle. Soupir - Il ya une raison pourquoi ce n'est pas possible par la conception. Angulaire n'est pas la faute de pour de mauvaises décisions en matière d'architecture ou des systèmes de legs que certaines personnes ont. Si vous souhaitez analyser existantes du code HTML libre à vous d'en utiliser un autre cadre Angulaire fonctionne parfaitement bien avec WebComponents. Réglage des limites claires pour guider les hordes de les programmeurs inexpérimentés est plus important que de permettre sale de hacks pour quelques systèmes existants.
Vous devez vous connecter pour publier un commentaire.
MODIFIER liées à 2.3.0 (2016-12-07)
Sujet similaire est question ici L'équivalent de $compiler Angulaire 2. Nous avons besoin d'utiliser
JitCompiler
etNgModule
. Lire plus à propos deNgModule
dans Angular2 ici:En un Mot
Il est un travail plunker/exemple (modèle dynamique, dynamique type de composant, module dynamique,
JitCompiler
, ... dans l'action)Le principal est:
1) créer un Modèle
2) trouver
ComponentFactory
en cache - aller à 7)3) - créer
Component
4) - créer
Module
5) - compiler
Module
6) - retour (et de mise en cache pour une utilisation ultérieure)
ComponentFactory
7) utilisation Cible et
ComponentFactory
pour créer une Instance de la dynamiqueComponent
Voici un extrait de code (plus de ici) - Notre Constructeur personnalisé est de retour juste construit dans le cache
ComponentFactory
et la vue de la Cible de l'espace réservé de consommer pour créer une instance de laDynamicComponent
C'est-il - en bref il. Pour obtenir plus de détails.. lire ci-dessous
.
TL&DR
Observer une plunker et revenir à lire les détails au cas où certains l'extrait de code nécessite plus d'explications
.
Explication détaillée - Angular2 RC6++ & les composants runtime
Ci-dessous la description de ce scénario, nous allons
PartsModule:NgModule
(titulaire de petits morceaux)DynamicModule:NgModule
, qui contiendra notre composant dynamique (et de référencePartsModule
dynamiquement)Component
type (seulement si le modèle a changé)RuntimeModule:NgModule
. Ce module inclut les créée précédemmentComponent
typeJitCompiler.compileModuleAndAllComponentsAsync(runtimeModule)
pour obtenirComponentFactory
DynamicComponent
- emploi de la Vue Cible de l'espace réservé etComponentFactory
@Inputs
à nouvelle instance (interrupteur deINPUT
àTEXTAREA
édition), consommer@Outputs
NgModule
Nous avons besoin d'un
NgModule
s.Il y aura un module pour tous les petits composants, par ex.
string-editor
,text-editor
(date-editor
,number-editor
...)Le deuxième module pour notre Dynamique trucs de manipulation. Il contiendra l'hébergement de composants et de certains fournisseurs.. qui sera singletons. Pour cela, nous les publierons façon standard - avec
forRoot()
Enfin, nous aurons besoin d'une adhoc, module d'exécution.. mais qui sera créé plus tard, comme une partie de
DynamicTypeBuilder
travail.Le quatrième module, module d'application, est celui qui fait ce que déclare compilateur fournisseurs:
Lire (lire) beaucoup plus sur NgModule là:
Un modèle constructeur
Dans notre exemple, nous traiterons en détail de ce genre de entité
Pour créer un
template
, dans ce plunker nous utilisons cette simple/naïve builder.Une astuce ici est - il construit un modèle qui utilise un ensemble de propriétés connues, par exemple
entity
. Ces biens(-ies) doivent faire partie de la composante dynamique, que nous allons créer par la suite.Pour le rendre un peu plus facile, nous pouvons utiliser une interface pour définir les propriétés de notre Modèle de générateur pouvez utiliser. Ce sera mis en œuvre par notre dynamique de type de Composant.
Un
ComponentFactory
constructeurChose de très important ici est de garder à l'esprit:
Nous sommes, donc, de toucher le cœur de notre solution. Le Constructeur, 1) créer
ComponentType
2) créer sonNgModule
3) compilerComponentFactory
4) cache pour les réutiliser ultérieurement.Une dépendance, nous devons le recevoir:
Et voici un extrait de comment obtenir une
ComponentFactory
:Et voici deux méthodes, qui représentent la façon vraiment cool comment créer un décorées classes/types à l'exécution. Non seulement
@Component
mais aussi la@NgModule
Important:
ComponentFactory
utilisé par le composant d'hébergementDernière pièce est une composante, qui accueille la cible pour notre composant dynamique, par exemple
<div #dynamicContentPlaceHolder></div>
. Nous obtenir une référence à elle et l'utilisationComponentFactory
pour créer un composant. C'est en un mot, et voici tous les morceaux de ce composant (si nécessaire, ouvrez plunker ici)Nous allons d'abord résumer les déclarations d'importation:
Nous venons de recevoir, le modèle et les producteurs de composantes. À côté sont des propriétés qui sont nécessaires pour notre exemple (plus dans les commentaires)
Dans ce scénario simple, notre hébergement composant n'a pas de
@Input
. Afin de ne pas avoir à réagir aux changements. Mais en dépit de ce fait (et pour être prêt pour les changements à venir) - nous avons besoin d'introduire quelques drapeau si le composant a déjà été (d'abord) initié. Et seulement alors nous pouvons commencer la magie.Enfin, nous allons utiliser notre générateur de composants, et de ses compilé juste le cache
ComponentFacotry
. Notre Cible de l'espace réservé sera demandé pour instancier laComponent
avec cette usine.petite extension
Aussi, nous avons besoin de garder une référence de modèle compilé.. pour pouvoir correctement
destroy()
, chaque fois que nous allons changer.fait
Qui est à peu près tout. N'oubliez pas de Détruire rien de ce qui a été construit de manière dynamique (ngOnDestroy). Aussi, assurez-vous de cache dynamique
types
etmodules
si la seule différence est leur modèle.Vérifier tout cela en action ici
directives
mot-clé dans@component
(type.builder.ts
). N'est-ce pas dépréciée depuis RC5? Si oui, est-il une solution qui permet d'éviter cela? Je pense mettre@ngmodule
's dans laapp/parts/*.ts
, mais n'ont pas été couronnée de succès pour l'instant...type.builder.ts
. Tout le reste n'est utile que pour l'exemple qu'il utilisait pour écrire cela. Il est beaucoup plus simple que ce qu'il a à être.type.builder.ts
comme vous l'avez indiqué, je souhaite, que tout utilisateur serait de comprendre comment placer tous dans son contexte... Espérons qu'il pourrait être utile 😉createNewComponent
ne compile pas avec cette erreur:Return type of public method from exported class has or is using private name 'CustomDynamicComponent'
. Des idées?tsconfig.json
j'avais"declaration": true
. En le définissant àfalse
ou la suppression il corrige l'erreur!MODIFIER (26/08/2017): La solution ci-dessous fonctionne bien avec Angular2 et 4. Je l'ai mis à jour pour contenir une variable de modèle et cliquez sur gestionnaire et testé avec Angulaire 4.3.
Pour Angular4, ngComponentOutlet comme décrit dans Ophir réponse est une bien meilleure solution. Mais pour l'instant il ne prend pas en charge les entrées & sorties encore. Si [ce RP](https://github.com/angular/angular/pull/15362%5D est accepté, il sera possible à travers l'instance de composant retourné par l'événement de création.
ng-dynamique-composant peut être la meilleure et la plus simple solution tout à fait, mais je n'ai pas testé encore.
@Long du Champ de réponse est sur place! Voici un autre (synchrone) exemple:
Vivre à http://plnkr.co/edit/fdP9Oc.
ngAfterViewInit
appel avec unconst template
ne fonctionne pas. Mais si votre travail a été de réduire l'détaillées ci-dessus décrit l'approche de (créer un modèle, créer un composant, création du module, de les compiler, de créer de l'usine.. créer une instance)... vous n'avez probablement il{{1 + 1}}
à mon débarquez au-dessus et il fonctionne très bien.Uncaught (in promise): Error: Error in ./TemplateComponent class TemplateComponent - inline template:0:3 caused by: Expression has changed after it was checked. Previous value: 'CD_INIT_VALUE'. Current value: 'Example template: 2'. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?
TemplateComponent
et de transmettre les valeurs? Par exemple, je veux que mon modèle pour contenir{{row[columnDef.field]}}
. Comment puis-je créer un@Input
pourrow
etcolumnDef
sur monTemplateComponent
? Je pense que vous pouvez supposer que je suis en train de faire...TemplateComponent
et les mettre dans le parent de code une fois que le composant a été créé? Ou êtes-vous à l'aide du modèle de composant ailleurs par le biais d'un sélecteur vous avez attribué à celui-ci?(click)="actions()"
comment pourrais-je faire d'elle et de faire usage de l'Entrée et de la Sortie ici. il serait utile de voir ces fonctionnalités dans votre plunker.Je doit être arrivé à la fin de la partie, aucune des solutions ici semblait utile pour moi - trop salissant et ressenti comme trop d'une solution de contournement.
Ce que j'ai fini par faire, c'est à l'aide de
Angular 4.0.0-beta.6
's ngComponentOutlet.Cela m'a donné le plus court, le plus simple solution de tous les écrits dans la dynamique de fichier du composant.
my-component
- le composant dans lequel un composant dynamique est renduDynamicComponent
- le composant à être construite dynamiquement et il est rendu à l'intérieur de mon composantN'oubliez pas de mettre à jour tous les angles bibliothèques ^Angulaire 4.0.0
Espère que cette aide, bonne chance!
Mise à JOUR
Travaille aussi pour angulaires 5.
DynamicComponent
classe à l'intérieur d'une fonction, car il peut être long de classe dans mon casng build --prod --aot=false --build-optimizer=false
J'ai décidé de compact tout ce que j'ai appris en un seul fichier.
Il y a beaucoup à prendre dans ici, surtout par rapport à avant RC5. Notez que ce fichier source contient le AppModule et AppComponent.
Juin 2019 réponse
Une excellente nouvelle! Il semble que la @angulaire/cdk paquet a maintenant le soutien de première classe pour portails!
Au temps de l'écriture, je n'ai pas trouvé la-dessus officielle docs particulièrement utile (notamment pour l'envoi de données vers et à recevoir des événements de la dynamique de composants). En résumé, vous aurez besoin de:
Étape 1) mise à Jour de votre
AppModule
Importation
PortalModule
de lacdk
paquet et enregistrer votre composante dynamique(s) à l'intérieur deentryComponents
L'étape 2. Option A: Si vous n'avez PAS besoin de passer des données et recevoir des événements à partir des composants dynamiques:
Le voir en action
L'étape 2. Option B: Si vous avez besoin de transmettre des données et recevoir des événements à partir des composants dynamiques:
Le voir en action
Portal
approche différente dengTemplateOutlet
etngComponentOutlet
?J'ai un exemple simple pour montrer comment le faire angulaire 2 rc6 composante dynamique.
Dire, vous avez un dynamic html template = template1 et souhaitez dynamique de la charge, d'une part envelopper dans la composante
ici template1 comme html, peut être contient ng2 composant
De rc6, ont @NgModule envelopper ce composant. @NgModule, tout comme le module dans anglarJS 1, il découpler les différentes partie de ng2 application, donc:
(Ici importation RouterModule comme dans mon exemple il y a une route de composants dans mon code html comme vous pouvez le voir plus tard)
Vous pouvez maintenant compiler DynamicModule que:
this.compiler.compileModuleAndAllComponentsAsync(DynamicModule).then(
factory => factory.componentFactories.find(x => x.componentType === DynamicComponent))
Et nous avons besoin de mettre ci-dessus en application.moudule.ts à charge, s'il vous plaît voir mon application.moudle.ts.
Pour plus d', et plein de détails, consultez le:
https://github.com/Longfld/DynamicalRouter/blob/master/app/MyRouterLink.ts et app.moudle.ts
et voir démo: http://plnkr.co/edit/1fdAYP5PAbiHdJfTKgWo?p=preview
Résolu ce Angulaire 2 version Finale en utilisant simplement la dynamicComponent directive de ng-dynamique.
Utilisation:
Où le modèle est votre modèle dynamique et le contexte peut être défini dynamique modèle de données que vous voulez que votre modèle de lier à.
Je tiens à ajouter quelques détails sur le dessus de ce très excellent post de Radim.
J'ai pris cette solution et a travaillé sur elle pour un peu, et a vite couru dans certaines limites. Je vais juste le contour de celles-ci et de donner ensuite la solution à ça aussi.
dynamique-détail (en gros nid dynamique de l'Isu à l'intérieur les uns des autres).
une des pièces qui a été rendu disponible dans la solution. Qui a été
pas possible avec la solution initiale soit.
J'ai fait une autre question en se basant sur ce post, sur la façon d'atteindre ces limites, qui peut être trouvé ici:
récursive modèle dynamique de la compilation dans angular2
Je vais juste décrire les réponses à ces limitations, vous devez exécuter dans le même problème que j'ai, comme qui en font une solution très flexible. Il serait génial d'avoir la première plunker mis à jour en tant que bien.
Pour permettre l'imbrication dynamique de détail à l'intérieur de chacun d'autres, Vous aurez besoin d'ajouter DynamicModule.forRoot() dans l'instruction d'importation dans le type.générateur de rapports.ts
D'ailleurs qu'il n'était pas possible d'utiliser
<dynamic-detail>
à l'intérieur de l'une des pièces de la chaîne d'éditeur ou un éditeur de texte.Pour permettre que vous devez changer
parts.module.ts
etdynamic.module.ts
À l'intérieur de
parts.module.ts
Vous aurez besoin d'ajouterDynamicDetail
dans leDYNAMIC_DIRECTIVES
Également dans le
dynamic.module.ts
vous seriez obligé de supprimer le dynamicDetail comme ils le font maintenant partie des piècesUn travail modifié plunker peut être trouvé ici: http://plnkr.co/edit/UYnQHF?p=preview (je n'ai pas de résoudre ce problème, je suis juste le messager :-D)
Enfin, il n'était pas possible d'utiliser templateurls dans les pièces créées sur la dynamique des composants. Une solution (ou une solution de contournement. Je ne suis pas sûr de savoir si c'est un angulaires bug ou d'une mauvaise utilisation du cadre) a été de créer un compilateur dans le constructeur au lieu de l'injecter.
Puis utilisez le
_compiler
pour compiler, puis templateUrls sont activés ainsi.Espère que cela aide quelqu'un d'autre!
Cordialement
Morten
Suivi Radmin est une excellente réponse, il y a une petite astuce nécessaire pour tout le monde qui est à l'aide angulaires-cli version 1.0.0-bêta.22 et au-dessus.
COMPILER_PROVIDERS
ne peuvent plus être importés (pour les détails, voir angulaires-cli GitHub).Donc la solution de contournement est de ne pas utiliser
COMPILER_PROVIDERS
etJitCompiler
dans leproviders
l'article, mais l'utilisationJitCompilerFactory
de '@angulaire/compilateur' à la place comme ceci à l'intérieur du type constructeur de la classe:Comme vous pouvez le voir, il n'est pas injectable et donc n'a pas de dépendances avec le DI. Cette solution devrait également fonctionner pour les projets à l'aide angulaires-cli.
Angulaire 7.x j'ai utilisé angulaires-éléments pour cela.
Installer @angulaires-éléments
npm i @angulaire des éléments -s
Créer des accessoires de service.
Note que vous avez personnalisées balise de l'élément doit être différent angulaire composant sélecteur.
dans AppUserIconComponent:
et dans ce cas, la coutume nom de la balise, j'ai utilisé "l'utilisateur icône".
ou comme ceci:
(dans le modèle):
Noter que dans le deuxième cas, vous devez passer des objets JSON.stringify et après que de l'analyser à nouveau. Je ne peux pas trouver une meilleure solution.
document.createElement(tagName);
Je suis moi-même en train de voir comment je peux mettre à jour le RC4 pour RC5 et donc je suis tombé sur cette entrée et la nouvelle approche de la dynamique de la création de composant contient encore un peu de mystère pour moi, donc j'ai l'habitude de proposer quoi que ce soit sur la composante de l'usine de résolution.
Mais, ce que je peux suggérer, c'est un peu plus claire de la démarche de création d'un composant sur ce scénario, utilisez simplement basculer dans un modèle qui permettrait de créer de la chaîne de l'éditeur ou un éditeur de texte en fonction de certaines conditions, comme ceci:
Et par la manière, " [ " , dans [prop] expression ait un sens, cela indique un moyen de liaison de données, d'où vous pouvez et même devez omettre ceux dans le cas où si vous savez que vous n'avez pas besoin de lier la propriété de la variable.
switch
/case
contient quelques décisions. Mais imaginez que le modèle pourrait être vraiment grand... et diffèrent pour chaque entité, diffèrent par la sécurité, se distinguent par le statut de l'entité, par chaque type de propriété (nombre, date, référence, éditeurs...) ... Dans ce cas, la résolution de ce dans le modèle html avecngSwitch
serait de créer un grand, très très grandhtml
fichier.C'est l'exemple de la dynamique de contrôles de Formulaire généré à partir du serveur.
https://stackblitz.com/edit/angular-t3mmg6
Cet exemple est dynamique contrôles de Formulaire est à ajouter un composant (C'est là que vous pouvez obtenir le Formcontrols à partir du serveur). Si vous voyez addcomponent méthode, vous pouvez voir les Contrôles de Formulaires. Dans cet exemple, je ne suis pas en utilisant angulaire de matériel,mais Il fonctionne (je suis en utilisant @ work). C'est la cible angulaire 6, mais fonctionne dans toutes les versions précédentes.
Besoin d'ajouter JITComplierFactory pour AngularVersion 5 et au-dessus.
Grâce
Vijay
Pour ce cas particulier, ressemble à l'aide d'une directive pour créer dynamiquement le composant serait une meilleure option.
Exemple:
Dans le code HTML où vous voulez créer le composant
Je l'approche et la conception de la directive de la manière suivante.
Dans votre composants de texte, string, date, quelle que soit la quelle que soit la configuration que vous avez été de passage dans le code HTML dans le
ng-container
élément serait disponible.La config,
yourConfig
, peut être le même et de définir les métadonnées.En fonction de votre config ou le type d'entrée de la directive doit agir en conséquence et de types pris en charge, il aurait rendu le composant approprié. Si non il va se connecter une erreur.
De construction sur le dessus de la réponse par Ophir Stern, voici une variante qui fonctionne avec AoT Angulaire 4. Le seul problème que j'ai est que je ne peux pas injecter de tous les services dans le DynamicComponent, mais je peux vivre avec ça.
remarque: je n'ai pas testé avec Angulaire 5.
Espère que cette aide.
Cheers!