Angular: Proposition : Besoin de pouvoir ajouter des directives aux éléments hôtes dans la déclaration de composant.

Créé le 23 mai 2016  ·  114Commentaires  ·  Source: angular/angular

J'ai creusé dans Angular 2 et j'ai rencontré un obstacle potentiel pour étendre certains types de composants.

Dans l'exemple suivant, j'ai un composant de bouton et une directive qui appliquera des styles basés sur des événements tactiles. Il y aura de nombreux autres objets autres que le bouton qui hériteront exactement du même comportement tactile. J'ai exploré mes options, et je suis perdu :

  • Étendez directement une TouchClass. Cela semble loin d'être idéal car le typescript ne prend pas en charge l'héritage de classes multiples, et j'aimerais également exposer le comportement aux consommateurs pour une utilisation dans leurs propres classes.
  • Faux héritage de classes multiples via une interface. Cela ressemble à un hack et m'oblige à redéclarer une API de shim sur chaque classe dans laquelle j'essaie de mixer. https://www.stevefenton.co.uk/2014/02/TypeScript-Mixins-Part-One/
  • Créez une fonction d'assistance qui le fait via un service directement sur elementRef.nativeElement dans le constructeur de composant. Je ne veux vraiment pas faire cela car il indique dans la documentation que nativeElement sera nul lors de l'exécution dans un travailleur, et cette capacité est quelque chose qui me passionne le plus.

Sans entrer trop profondément dans les tripes, je suppose que le componentMetadata est disponible pendant la compilation des composants, et que la propriété hôte pourrait être analysée pour des directives supplémentaires qui pourraient être ajoutées dynamiquement et compilées en même temps. Cela vous permettrait de faire des mixins de manière angulaire : en utilisant des directives composables pour étendre les fonctionnalités, et en le faisant sans casser la projection de la vue. Petit exemple ci-dessous.

Comportement actuel
Déclarer une directive dans componentMetadata.host la traite comme un attribut régulier

Comportement attendu/souhaité
La directive déclarée dans l'hôte serait traitée au moment de la compilation.

/**
 * App
 */
@Component({
    selector: 'app-component',
    template: '<g-btn>TEST</g-btn>',
    directives: [gBtn, gTouch]
})

export class AppComponent {
    constructor() {

    }
}

/**
 * Touch Directive
 * Will be used in lots and lots of components
 */
@Directive({
    selector: '[g-touch]',
    host: { 
        '(touchstart)': '...',
        '(touchend)': '...',
        '(touchmove)': '...',
        '(touchcancel)': '...'
    }
})

export class gTouch {
    constructor() {

    }
}

/**
 * Simple button component
 */
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    host: {
        'role': 'button',
        // WOULD LOVE FOR THIS TO COMPILE THE DIRECTIVE!
        // right now it just adds an attribute called g-touch
        'g-touch': ' ' 
    }
})

export class gBtn {

    constructor() {

    }
}

Quelques idées sur la façon dont cela pourrait fonctionner:

// Option 1: just scan the host properties for directives.
// This would be my ideal, simple and understandable
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    host: {
        'role': 'button',
        'g-touch': true // or {prop: 'foo'} or string
    }
})

// Option 2: definitely more declarative using a hostDirectives property
// more declarative, albeit more annoying to have to reimport the touch class
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    hostDirectives: gTouch,
    host: {
        'role': 'button',
        'g-touch': true
    }
})

// Option 3: declare host directives as its own thing, still just
// use keys pointing to bool, obj, or string
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    hostDirectives: {
        'g-touch': {someOption: someOption}
    },
    host: {
        'role': 'button',
    }
});

// Option 4: Not a huge fan of this one, but understandable if
// people want to keep one host property
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    host: {
        'role': 'button',
        _directives: {
            'g-touch': true
        }
    }
});

Merci à tous, Angular 2 a fière allure !. Faites-moi savoir s'il y a quelque chose qui m'échappe.

core directive matching host and host bindings feature

Commentaire le plus utile

@IgorMinar le travail Ivy rend cela plus faisable. Mais oui après la v6.

Tous les 114 commentaires

Je développe actuellement un gros client et j'essaie donc de décomposer tous les problèmes liés à l'interface graphique en directives Angular2 réutilisables. Cela m'amène toujours au même problème, comme James l'a parfaitement souligné.
Cela doit vraiment fonctionner d'une manière ou d'une autre pour une bonne architecture modulaire et dynamique. L'exemple tactile n'est qu'un des nombreux scénarios où cela est nécessaire. par exemple glisser-déposer, redimensionner l'observation, etc. etc. etc.
Fait un autre exemple en tant que plunker :
https://plnkr.co/edit/J65THEMic0yhObt1LkCu?p=info

Y a-t-il une chance que cette fonctionnalité soit ajoutée prochainement ?

Voici une question StackOverflow liée à cela : http://stackoverflow.com/questions/37148080/use-angular2-directive-in-host-of-another-directive

@ Andy1605 avez-vous déjà trouvé un moyen de contourner cela? J'ai en quelque sorte proposé de travailler avec NG2 à cause de cela pendant les CR. J'adorerais le récupérer, mais ce problème particulier m'empêche de créer des modèles d'interface utilisateur extensibles.

Je pense également qu'il manque à Angular une fonctionnalité essentielle ici. Il devrait être possible pour un composant de déclarer (plusieurs) directives d'attribut pour son hôte. Ne pas pouvoir le faire est aussi un obstacle majeur pour mon projet.
Est-ce que quelqu'un sait si cela sera mis en œuvre à l'avenir ou s'il y a des raisons pour lesquelles cela ne peut pas être fait?

J'ai proposé une solution à ce problème (bien que pour la version angulaire 1) ici : https://github.com/angular/angular.js/issues/15270.

Mon idée est qu'au lieu de simplement avoir la possibilité d'ajouter des directives, le framework de compilation aurait un nouveau point d'extensibilité appelé "hostTransforms" (dans le cas d'angular 1, "nodeTransforms") qui aurait accès à la déclaration de composant non modifiée et non filtrée et le nœud hôte du composant d'origine, non compilé, chaque fois qu'un composant est rencontré pour la première fois par le compilateur et en cours de préparation pour insertion dans le DOM. De cette façon, un développeur pourrait étendre les décorateurs de composants avec des propriétés personnalisées, puis utiliser nodeTransforms pour convertir ces propriétés personnalisées en quelque chose avec lequel le framework angulaire est familier, juste avant la compilation. Consultez le fil de demande de fonctionnalité pour des exemples.

Je connais mieux le code source angulaire que le code source angulaire 2, donc je ne sais pas si le processus de mise en œuvre serait le même ici. Mais comme cela semble être une demande assez populaire, j'aimerais la voir soit implémentée dans angular 2 et rétroportée, soit implémentée dans angularjs et transférée (est-ce une chose?).

+1

Je dois être d'accord, une fonctionnalité qui nous permet d'ajouter des directives d'attributs contribuant à l'hôte serait formidable. Je sais que je pourrais utiliser une telle fonctionnalité dès maintenant en implémentant une manière plus "angulaire" d'ajouter une fonctionnalité de glisser/déposer à mes composants d'interface utilisateur.

Que diriez-vous de créer une nouvelle balise similaire à <ng-container> qui vous permet de les appliquer dans le modèle du composant au lieu de la propriété de métadonnées host ? Quelque chose comme <ng-host [attributeDirective]> pour indiquer que les directives sont ajoutées au composant hôte.

@jjstreet, votre proposition ressemble à replace: true (évidemment pas identique, mais similaire), qui était obsolète il y a quelque temps. Mais peut-être que replace: true était obsolète pour une raison qui ne s'appliquerait pas ici.

@pkozlowski-opensource Pourrions-nous obtenir une réponse quelconque de l'équipe ng2 à ce sujet ?

Je suis prêt à tout pour y parvenir. J'ai suggéré la propriété host car elle a accès à la portée locale du composant et elle ajoute déjà des attributs au composant lui-même. Les directives semblent être une extension naturelle de ce comportement.

+1 cette fonctionnalité est requise pour avoir un code propre et réutilisable dans les composants de l'interface utilisateur

+1

Pourrions-nous s'il vous plaît obtenir une sorte de réponse de l'équipe ng2 à ce sujet ? Même si c'est juste pour dire que vous n'allez pas le faire, ou pour dire que c'est une bonne idée mais pas une priorité actuelle, j'aimerais juste entendre une sorte de contribution.

J'aimerais ajouter un autre cas d'utilisation pour cela. Cela permettrait à ng2-mobx (https://github.com/500tech/ng2-mobx) de se débarrasser du composant d'emballage et d'avoir l'air beaucoup plus propre.

J'aimerais bien avoir ça aussi. Actuellement, j'en ai besoin pour créer une directive personnalisée routerLink . J'aimerais réutiliser un angulaire et lui fournir simplement les paramètres préparés par la directive mi.

Ainsi, au lieu de <a [routerLink]="repeatedCodeToGetLink()"> j'aurais <a [myRouterLink]> et cela appliquerait dynamiquement [routerLink] avec des paramètres résolus.

Vraiment excité par les perspectives de cela!

Nous en avons besoin depuis un moment. En fait, il y a quelque temps, avant de savoir qu'il y avait un problème ouvert, j'ai posé des questions sur le débordement de la pile à propos de cette fonctionnalité.

J'ai fourni un exemple élaboré de la façon dont nous pourrions utiliser cette fonctionnalité pour résoudre https://github.com/angular/flex-layout/issues/162 que nous avons ouvert depuis un certain temps. ( Voir l'exemple et l'explication ici )

Nous attendons avec impatience vos commentaires, je vois que ce problème est le troisième plus consulté de tous les problèmes ouverts dans ce dépôt. Espérons que nous pourrons le voir dans la prochaine version ou plus tôt (croisons les doigts) !

/cc @tbosch @IgorMinar @mhevery @jelbourn @hansl @ThomasBurleson

@jjstreet je pense que votre suggestion

<ng-host myDirective="foo"></ng-host> 

... irait bien avec une autre proposition distincte qui a été faite il y a quelque temps pour des raisons distinctes de celles dont nous discutons ici.

Voir https://github.com/angular/angular/issues/7297

Actuellement, je contourne ce problème en ajoutant une directive dans le composant parent, puis en ajoutant un écouteur dans l'hôte avec @HostListener.

Parent.html
<my-component myDirective>

Composant.ts
@HostListener('myEvent') handler() { // do stuff }

Mais ce serait plus propre si on pouvait ajouter des attributs directement dans l'hébergeur...

Voici comment j'ai géré cela, mais je pense vraiment que la mise en œuvre de cette fonctionnalité à partir du sol serait la meilleure solution.

Juste un rappel mensuel que nous attendons des commentaires positifs ou négatifs à ce sujet de la part de l'équipe Angular.

@tbosch - Toute réflexion publique sur la priorité de ce problème. Cela a également un impact sur @angular/flex-layout .

@fadzic ne pouvez-vous pas simplement ajouter la directive à l'élément hôte en faisant cela ...

Composant.ts
@HostBinding('attr.myHilite') myHilite = new myHiliteDirective()

ou comme ceci si vous avez besoin de paramètres comme ElementRef ou Renderer2
@HostBinding('attr.myHilite') myHilite = new myHiliteDirective(this.elementRef, this.renderer)

J'ai également besoin d'ajouter une directive à l'élément host et j'ai été redirigé vers ce problème. J'ai pu faire ce dont j'avais besoin en utilisant le code ci-dessus. Je ne suis en aucun cas un expert de l'utilisation d'angular, mais cette solution de contournement semble fonctionner jusqu'à présent, si quelqu'un avait des problèmes avec cette approche, faites-le moi savoir. Merci.

@btinoco qui ne fonctionne pas car aucune méthode de cycle de vie n'est appelée. Vous devrez tout câbler manuellement dans chaque composant qui utilise la directive plutôt que de simplement le câbler pour vous.

@hccampos merci pour l' ngOnInit de ma directive n'a pas été exécuté ( à moins d' utiliser la directive dans mon élément manuellement) ou j'appelle de la directive ngOnInit() de mon composante ngOnInit() . Encore merci de me l'avoir signalé.

@btinoco - oui. c'est une question subtile mais désagréable. Celui que @angular/flex-layout espère être corrigé bientôt. ;-)

Des nouvelles de l'équipe Angular à ce sujet ? Cela fait 1 an que le problème a été ouvert...

Trouver cette description détaillée sur ce problème était super cool,
puis trouver aucun retour de l'équipe Angular était super pas cool :(

Concernant les solutions déjà fonctionnelles :

Cette demande de fonctionnalité ressemble beaucoup à des mixins. En fait, puce n°2 dans la description
de cette fonctionnalité correspond en fait à l'officiel
documentation de TypeScript, voir ici .
En angulaire, cela devient un peu pire cependant, car pour mélanger une classe avec des @Input() s, vous
doivent les re-déclarer sur la classe de base.

Une autre solution qui fonctionne déjà aujourd'hui serait de faire en sorte que le composant contienne un élément wrapper et d'y appliquer les directives.
Par exemple, si le composant contenait un modèle comme <wrapper g-touch>...

Concernant "Créer une fonction d'assistance qui le fait via un service directement sur elementRef.nativeElement":
Oui, cela semble être une bonne idée aussi. Je ne me soucierais pas de WebWorkers pour l'instant,
car ils sont encore expérimentaux et manquent de fonctionnalités plus importantes pour la production,
et presque aucune bibliothèque ne fonctionnerait sur WebWorkers.
Voir par exemple aussi notre bibliothèque de matériaux qui accède directement au DOM.

Concernant l'option 1) de la proposition :

La sémantique actuelle pour les liaisons de propriétés d'hôte est,
qu'ils définissent une propriété myDir sur l'élément HTML sous-jacent,
mais pas n'importe quelle directive. Cependant, si host peut également introduire des directives, les utilisateurs peuvent écrire ce qui suit
et serait confus pourquoi cela ne met pas à jour la propriété dans la directive myDir :

@Component({
  host: {
    '[myDir]': true
  },
  template: '...'
})
class MyComp {}

Concernant l'option 1) et l'option 3) :
L'introduction d'une sorte de liaisons host entre les directives sur le même élément peut :

  • conduire à un cycle dans le graphique de liaison de données, qu'Angular ne prend pas en charge, et donc
    conduire à des erreurs difficiles à déboguer en raison de valeurs obsolètes / erreurs "L'expression a changé après vérification".
  • conduire à un surcoût de perf supplémentaire, par rapport aux directives qui s'injectent les unes les autres
    et communiquer directement.

Concernant l'option 2) de la proposition :

  • oui, devoir se référer à la classe gTouch semble étrange, comme toutes les autres directives
    sont déclenchés via NgModule s.

@ThomasBurleson parlons hors ligne de votre cas d'utilisation plus en détail...

@tbosch J'aimerais proposer une autre option : introduire une balise angulaire native, appelons-la <ng-host> .

Remarque : @mhevery a proposé l'introduction d'une balise <ng-host> dans https://github.com/angular/angular/issues/7546 , cependant, même si j'utilise le même nom de balise ici, ce que je suis la proposition est distincte et vise spécifiquement à traiter la question qui a été soulevée ici.

La balise ng-host ne serait pas implémentée en tant que classe de directive/composant ordinaire, mais serait plutôt un code de framework "magique"... similaire à ng-content , ng-container , etc. .,
La balise servirait simplement de "pointeur" vers l'hôte du composant d'une manière analogue au sélecteur css

Cela évite les scénarios ambigus, chaque composant ne serait autorisé à avoir, au plus, qu'un bloc <ng-host> et il devrait s'agir de la balise/nœud racine du modèle de ce composant.

Voici comment on l'utiliserait :

// Option 5: Use `<ng-host>`.. Very declarative and intuitive
@Component({
  selector: 'g-btn',
  template: `
    <!-- 
      Besides comments, having dom code inside the template but outside of a declared 
      ng-host code block would raise an error (hopefully at compile-time) .
    -->

    <ng-host role="button" g-touch> 
      <ng-content></ng-content>
    </ng-host>
  `
})

Au fait @tbosch , Merci d'avoir répondu à tous. Nous apprécions vraiment votre engagement et vos commentaires sur cette question.

Les réflexions de tout le monde sur cette fonctionnalité sont-elles spécifiques aux composants, ou serait-il également logique qu'une directive puisse appliquer une directive différente à son hôte ? Le cas d'utilisation pour lequel j'ai commencé à souscrire à ce problème impliquait quelques directives tierces que A) nous voulions isoler de notre code au cas où nous voulions changer plus tard et B) voulions appliquer des fonctionnalités par défaut à chaque instance sans avoir à dupliquer la configuration à chaque fois que nous l'avons utilisé.

Par exemple, une directive d'info-bulle, qui va être appliquée sur un grand nombre d'éléments dans toute notre application, et nous voulons définir par défaut le délai et appendToBody (il ne prend pas en charge un objet de configuration centralisé). Parce qu'il ne supportait pas un objet de configuration central, nous avons dû mettre trois ou quatre attributs partout où nous voulions l'utiliser. Et puis plus tard, nous avons fini par nous éloigner de cette bibliothèque (nous avons commencé à utiliser les info-bulles des matériaux) et nous avons dû remplacer manuellement chaque info-bulle. Si nous avions pu créer notre propre directive qui l'avait "encapsulée", cela aurait été aussi simple que de changer cette directive pour appliquer [mdTooltip] à son hôte au lieu de l'autre bibliothèque.

@MikeMatusz On dirait que j'avais aussi cela en tête, voici mon extrait de https://github.com/angular/flex-layout/issues/162#issuecomment -290350270.

@Directive({
  selector: 'fxLayoutFullPage',
  hostDirectives: [LayoutDirective],
  host: { 
    'fxLayout': 'column', 
    'style': 'min-height:100vh; background-color:yellow'
  }, 
}) class LayoutFullPageDirective {}

Serait-il possible de créer un décorateur de propriété qui instancie une directive ?
Par exemple:
@HostDirective(LayoutDirective) myLayoutDirective: LayoutDirective;

Cela fonctionnerait pour les composants ainsi que pour les directives, fournirait une référence d'instance pour l'interaction et ne serait pas perdu lors de l'héritage du composant/de la directive.
Je suppose que cela devient plus compliqué si vous souhaitez également fournir des liaisons d'entrée et d'événement.

Où cela se situe-t-il ? Je suis assez nouveau sur Angular2/4, et ce que je veux faire, c'est créer une directive qui applique simplement plusieurs autres directives à la fois. Alors qu'au lieu de :

<button directiveA directiveB directiveC>BUTTON TEXT</button>

Je peux juste écrire :

<button customDirectiveABC>BUTTON TEXT</button>

On dirait que cela devrait être facile - composition de base/DRYness. Mais pour autant que je sache, ce n'est pas possible ?

@soynog , je ressens exactement la même chose. J'aimerais aussi savoir où cela se situe.

J'espérais pouvoir créer des boîtes de dialogue déplaçables en utilisant Angular Material et angular2-draggable (puisque angular/material#1206 n'est pas encore pris en charge) où j'aimerais ajouter dynamiquement une directive au md-dialog-container que MdDialog service crée, mais il semble beaucoup plus difficile d'obtenir le comportement du compilateur Angular 1.x ici pour les directives dynamiques.

@tbosch , @ThomasBurleson , le cas d'utilisation hors ligne dont vous avez discuté était-il lié aux problèmes ou aux objectifs que Thomas a soulevés par hasard dans angular/material#1206 ? J'essaie juste de comprendre les changements de comportement entre les frameworks 1.6.x et 2+.

Y a-t-il des mises à jour sur ce problème? Il a gagné du terrain au début, mais je pense qu'il ne reçoit plus aucune attention.

Yup aucune mise à jour à ce sujet?

C'est quelque chose dont j'ai tellement besoin, j'espère que cette proposition parviendra en amont.

Ce serait bien, j'ai réalisé aujourd'hui que je ne peux pas appliquer de directives par programmation/dynamique, je suis devenu triste.

+1
Pareil pour moi :)
Je cherche un moyen d'encapsuler plusieurs directives dans une directive personnalisée qui fait tout ce dont j'ai besoin. Par exemple :

<my-cmp [myDirective]="content"
        [isOpen]="myCondition"
        customProp2="customClass"
        customProp1="customText">
 ...
</my-cmp>

Ce serait bien si je pouvais créer une directive qui enveloppe toutes ces choses afin que je puisse les réutiliser sans copier/coller toutes les lignes.

<my-cmp myCustomDirective>
</my-cmp>

Et dans ma directive personnalisée

<ng-host [myDirective]="content"
        [isOpen]="myCondition"
        customProp2="customClass"
        customProp1="customText">
</ng-host>

à venir à l'occasion du deuxième anniversaire de ce numéro ! Honnêtement, cette fonctionnalité serait tellement utile qu'elle nous permet de créer des composants et des directives hautement composables sans avoir à créer un million de wrappers. composez simplement le composant dont vous avez besoin à partir des directives que vous avez. simple, propre, efficace.

@IgorMinar - De toute façon, nous pouvons obtenir cette fonctionnalité sur le radar pour les améliorations à venir ?

J'aimerais savoir si une telle fonctionnalité serait considérée comme un mauvais modèle ou non. N'importe qui?

@darkbasic - AFAIU, sans cette fonctionnalité, un développeur aurait besoin d'introduire un élément wrapper (sur ng-container ) simplement pour ajouter des directives parentes à la vue et au contenu du modèle.

Non, je ne pense pas que pouvoir avoir le contrôle total de votre propre composant sans avoir à utiliser des wrappers est un mauvais modèle. C'est une nécessité.

@bradlygreen un commentaire ?

Cette fonctionnalité est la demande la plus populaire (sinon le top 5) parmi tous les numéros ouverts de ce référentiel... Sur Internet, nous voyons des rapports (soutenus par des données empiriques) sur le déclin d'Angular en tant que framework de facto... Je pense l'un des facteurs qui motivent cela est le sentiment que la communauté n'est pas entendue. La compétition; vue.js et réagissent, gagnent du terrain et ont dépassé les angles car même s'ils ne mettent pas nécessairement en œuvre tout ce que tout le monde veut, ils fournissent au moins des commentaires continus sur les éléments demandés les plus populaires. C'est tellement frustrant d'attendre si longtemps et de ne rien entendre... pas même un simple "non, nous ne le ferons pas".

(Voir la section Cadres Js « glissements angulaires » )

... même si je pense que certaines opinions sur Angular / Vue / React / ... sont influencées par différents facteurs ... cette fonctionnalité concrète mériterait vraiment une forme de mise en œuvre (même les circonstances sont un peu plus compliquées qu'un simple solution avec une simple liste de directives appliquées) ... donc la position concrète de l'équipe de base d'Angular serait la bienvenue ... 🥇

Pas d'ETA spécifique, mais nous travaillons à rendre cette catégorie de choses beaucoup plus facile dans le moteur de rendu en 2018.

Espérons que les choses s'améliorent considérablement en 2018. Nous perdons

Voir:

@somombo, cet article a été confirmé comme étant des conneries il y a longtemps

Les gens qui connaissent vraiment leur affaire se sont moqués de l'auteur et aucun d'entre eux ne l'a pris au sérieux, les likes viennent de réagir, vue fanboys, naturellement.

Donc, le fait est que ce problème ici est une priorité très faible pour l'équipe angulaire, en fait c'est la priorité la plus basse possible.

Voir la liste des priorités publiée sur AngularHQ (recherchez le numéro de problème 8785)

C'est le cas bien que ce problème ait suscité beaucoup de discussions et d'intérêt de la part de la communauté, comme le montre le nombre de commentaires.

Si vous êtes quelqu'un qui se soucie de ce problème et que vous aimeriez vraiment le voir mis en œuvre, alors au lieu d'attendre... bien honnêtement _potentiellement jamais_, vous pouvez peut-être remplir le sondage angulaire annuel officiel et faire savoir que vous vous sentez comme ce problème devrait être une priorité plus élevée et apprécierait de le voir rempli le plus tôt possible.

N'oubliez pas de remercier notre équipe angulaire pour tout l'excellent travail qu'ils ont accompli !

Je voudrais également voter pour cette fonctionnalité. Cela a été la cause de trop de chagrin en essayant de contourner ce problème.

@somombo s'il vous plaît ne lisez pas trop la priorité dans AngularHQ pour le moment. la formule prioritaire n'est pas pleinement étoffée. Cela dit, je pense que nous devrions revoir cette demande de fonctionnalité après les navires v6. Je crains que nous n'ayons pas la bande passante pour cela plus tôt et que travailler là-dessus entre en conflit avec un travail déjà en cours dans la zone compilateur/noyau.

Il ne s'agit pas d'une demande de réparation rapide. Je soupçonne que cela va demander un effort considérable pour le faire correctement, mais les choses sur lesquelles nous travaillons pour la v6 devraient rendre celle-ci beaucoup plus facile à implémenter.

@IgorMinar le travail Ivy rend cela plus faisable. Mais oui après la v6.

@IgorMinar et @mhevery Je ne

Ce n'est pas toujours clair pour nous, profanes, ce qui est une "solution rapide" et ce qui ne l'est pas. Cependant, à part le fait qu'il ne s'agit pas d'une solution rapide et qu'il doit être fait correctement, je suis particulièrement reconnaissant qu'il semble que vous pensiez également que ce sera une fonctionnalité utile pour angulaire.

Nous savons que vous êtes tous les deux très occupés et que vous ne pouvez pas répondre ainsi à chaque problème.
Vous avez donc notre sincère gratitude chaque fois que vous le faites. Nous sommes ravis et attendons avec impatience l'angular v6 et au-delà !

Merci pour tout l'excellent travail!

Vous pouvez faire en sorte que votre classe de composant étende ou implémente la classe directive. Si vous essayez d'appliquer la directive sous le capot, cela ne devrait probablement être que logique dans le composant.

export class gBtn extends gTouch

@NateMay , qui ne vous permet d'étendre qu'une seule classe. Ce problème concerne davantage la composition de plusieurs éléments de fonctionnalité à l'aide de directives.

@NateMay deux problèmes avec cela - d'abord, vous ne pouvez étendre qu'une seule classe, et deuxièmement, vous venez de rompre l'injection de dépendance.

J'ajoute juste mes deux cents. Je construis un SPA multicouche avec une disposition angulaire, matérielle et flexible, en utilisant les états imbriqués de @uirouter/angular. Ensuite, l'incapacité à appliquer facilement les directives flex aux éléments de composant est très limitante.

Alors votez pour cette fonctionnalité s'il vous plaît.

+1 pour cette fonctionnalité ajoutée

Il est possible d'ajouter une directive à un ng-container , qui n'apparaîtra pas dans le DOM.

J'en avais besoin pour l'API intersection-observer (qui déclenche des événements lorsque des éléments entrent / sortent de la fenêtre). J'ai une directive intersector , qui a des événements enter() et leave() lorsque l'élément devient visible/caché. J'ai certains composants qui doivent utiliser cette API en interne, mais je ne voulais pas ajouter de DIV supplémentaire dans le modèle.

Donc ce que j'ai fait était le suivant dans component.html :

<ng-container intersector (enter)="weCameOnScreen()" (leave)="byeBye()">
     ... components normal template ...
</ng-container>

Ensuite, le constructeur de directive intersector.directive.ts injecte le ElementRef .

    constructor(private intersectorElementRef: ElementRef) { ... }

Pour un élément DOM normal, vous opéreriez simplement sur intersectorElementRef.nativeElement , mais pour un ng-container le nœud est en fait un nœud de commentaire. Alors je vérifie juste si c'est un commentaire, et si c'est le cas, je monte d'un niveau.

public ngAfterViewInit(): void 
{
    // if the directive is applied to an ng-container must go a level up
    this.domElement = (this.intersectorElementRef.nativeElement.nodeType == 8) ? this.intersectorElementRef.nativeElement.parentElement : this.intersectorElementRef.nativeElement;

   registerIntersector(this.domElement ...);

Cela ne fonctionnera pas dans toutes les situations, mais ça me va pour le moment. Je pense que dans le compilateur IVY, ils n'utilisent peut-être plus de commentaires - cela peut donc casser. L'important était que j'ai une seule directive que je peux utiliser sur les nœuds DOM ou dans ce qui est effectivement un faux ' @HostBinding ' pour la directive.

J'espérais vraiment qu'il était possible d'ajouter des directives de manière dynamique. Je veux pouvoir encapsuler des directives de niveau inférieur dans des directives "d'ordre supérieur", plus abstraites. J'ai posé la question suivante sur le débordement de pile, et je me demandais s'il y aurait une solution pour cela à l'avenir : https://stackoverflow.com/questions/51608645/abstract-away-leaflet-directive-in-custom-directive

comme l'a dit @mhevery .. nous devons être patients et attendre que la version complète de ivy (ng v7.0.0 ?) débarque. Apparemment, ce sera beaucoup plus facile pour eux à implémenter avec ivy... Après ivy, il faut rappeler à l'équipe à quel point cette fonctionnalité est importante pour nous, pour qu'ils ne l'oublient pas 😉

Abonnez-vous à cela. Je dois également pouvoir attacher dynamiquement une directive à un composant que j'ai créé avec resolveComponentFactory/createComponent.

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentItem.component);

const componentRef = viewContainerRef.createComponent(componentFactory);
(<DynamicComponent>componentRef.instance).data = componentItem.data;
(<DynamicComponent>componentRef.instance).cssClassList = componentItem.cssClassList;
// Add directive to new component here
// componentRef.addDirective(someDirective)

Toute mise à jour???
J'ai rencontré un autre cas d'utilisation où j'utilise une directive tierce.
Dans certains scénarios, je dois supprimer/ajouter une directive sur un élément HTML de manière dynamique.
est-ce possible de quelque manière que ce soit ou encore en attendant la solution ?

@micronyks ... en fait, il n'est pas possible d'ajouter une directive dynamiquement. Il faut attendre Ivy qui devrait ajouter la possibilité de créer une telle fonctionnalité.

@mlc-mlapis mais aucun plan pour quand IVY arrivera-t-il ? dans quelle version ?

@micronyks ... Angular 7 par horaire.

Les gars, soyons raisonnables ici, Angular Team s'efforce de travailler sur plusieurs fonctionnalités énormes qui sont très demandées (PWA, SSR, Ivy et surtout Custom Elements) la dernière étant une fonctionnalité très prioritaire, comme je pouvais le comprendre, car beaucoup des grandes entreprises (comme Microsoft) le demandent depuis toujours, et il y a une raison à cela. Pour obtenir des éléments personnalisés efficaces, ils ont besoin d'Ivy, dès qu'ils en auront terminé avec Ivy, comme l' a dit

En attendant, au lieu de continuer à exiger cette fonctionnalité (dont j'ai aussi désespérément besoin d'ailleurs), nous pouvons aider l'équipe Angular à accélérer le processus, en testant les bêtas, en signalant des bogues, en aidant avec les documents, etc.

Rappelons-nous que Angular Team n'est même pas si grand, c'est juste une douzaine de personnes qui essaient de créer un cadre génial pour tout le monde, mais cela prend du temps.

... oui, il faut être un peu patient maintenant et attendre le moment où nous pourrons aider davantage avec Ivy ... lorsque le compilateur sera terminé et que des documents de conception détaillée seront disponibles.

@avatsaev Je peux être d'accord avec tout ce que vous avez dit. Vous ne devriez pas exiger des choses ici. Mais vous pouvez expliquer les problèmes que vous rencontrez lorsque vous travaillez avec Angular.

Je suis loin d'être un développeur Angular très expérimenté, mais certaines choses ne me semblent pas correctes ou ne sont pas expliquées assez clairement.

Je suis tombé sur ce problème parce que je veux encapsuler un composant/une directive tiers, sans avoir une abstraction qui fuit. Cela permet en partie d'avoir des directives dynamiques. Ce qui m'étonne, c'est que c'est assez compliqué de réaliser une telle chose.

Je construis un générateur de formulaire, en utilisant Angular Material et Flex-Layout, qui prend une configuration JSON et génère un formulaire. Cette fonctionnalité m'aiderait à appliquer les directives flex-layout au composant hôte lors de l'exécution. J'ai l'impression que l'un des plus gros atouts d'Angular est la possibilité de générer du code au moment de l'exécution à partir d'une configuration, cela contribuera grandement à rendre ce code plus polyvalent. Je voulais juste déposer un bon cas d'utilisation. Impatient ;)

C'est mon cas d'utilisation exact

@NateMay voici mon implémentation si vous souhaitez le vérifier.

@NateMay voici mon implémentation si vous souhaitez le vérifier.

pourriez-vous s'il vous plaît expliquer? Je suppose que vous voulez dire dynamic-field.directive

Le dynamic-field.directive fait des trucs fantaisistes, mais il se passe aussi beaucoup d'autres choses. Je viens d'ajouter CONTRIBUTING.md dans le dossier racine, qui contient des instructions pour la configuration locale. Méfiez-vous de l'utilisation dans tout ce qui est en production depuis quelques mois. Je fais de grands changements alors que je travaille vers une implémentation stable.

+1

De loin, mes solutions de contournement sont, elles ont toutes des inconvénients.

  1. has-it , définir une nouvelle propriété de membre en tant que directive dans ma classe de composant, transmettre tous les arguments de constructeur nécessaires à cette directive lors de l'appel de sa fonction constructeur (par exemple, ElementRef, ViewContainerRef, TemplateRef... toutes les variables injectables demandées) , et appelez manuellement son rappel de cycle de vie si c'est le cas, comme ngInit() ngAfterViewInit() à la fonction de rappel de cycle de vie correspondante du composant actuel.
@component(...)
class MyComponent {
   theDirective: TargetDirective;
   constructor(el: ElementRef) {
       this.theDirective = new TargeDirective(el);
   }

  ngOnInit() {
     this.theDirective.ngOnInit();
  }
  ...
}
  1. Wrapper tout dans le modèle de composants dans un modèle ng de niveau supérieur,
    <ng-template><div targetDirective>....</div></ng-template> rendre dans ngAfterViewInit() comme :
const vf = this.viewContainerRef.createEmbeddedView(this.templateRef);
vf.detectChanges();

De cette façon, Angular crée un autre element avec cette directive dessus et le contenu réel de mon composant à l'intérieur juste après l'élément de composant d'origine dans l'arborescence DOM.

<my-component></my-component>
<div targetDirective>....</div>

De cette façon, c'est comme ce que fait <route-outlet> .

Il y a des effets secondaires évidents

Quelqu'un peut-il confirmer si c'est désormais possible avec Ivy ? Si oui, quelqu'un a-t-il un exemple ?

Rappelons-nous que Angular Team n'est même pas si grand, c'est juste une douzaine de personnes qui essaient de créer un cadre génial pour tout le monde, mais cela prend du temps.

Cela pourrait être plus grand en ayant une communauté de contributeurs.

Cependant, la chance qu'un correctif contribué soit accepté est très faible.

Donc à la place nous revenons à une dizaine de personnes.

Quelqu'un peut-il confirmer si c'est désormais possible avec Ivy ? Si oui, quelqu'un a-t-il un exemple ?

Comme aucun mot pour l'instant, j'ai pensé fournir la chose la plus proche que j'ai pu trouver, qui est un article d'il y a quelque temps sur la mise en œuvre des mixins avec Ivy : https://blog.nrwl.io/metaprogramming-higher-order-components -et-mixins-avec-angulaire-lierre-75748fcbc310

Selon l'article, je pense qu'une solution possible au problème d'origine de ce fil est d'utiliser la nouvelle fonctionnalité appelée... "fonctionnalités".

... Vous pouvez imaginer que c'est un peu un cauchemar d'essayer de Google quoi que ce soit à propos de cette fonctionnalité. En espérant qu'ils publient bientôt de la documentation officielle sur Ivy ! :)

@nayfin crée également un concepteur/constructeur de formulaires visuels
Et après quelques mois de travail pour rester bloqué sur le fait, je n'ai aucun moyen de déployer une directive sur un div ajouté dynamiquement me rend fou .... Devrait être si inconscient d'appeler MyDirectiveFactory::apply(HTMLElement)

Cette fonctionnalité serait extrêmement bien accueillie car je me retrouve toujours à créer un seul div pour attacher des directives de niveau supérieur. De plus, si je veux des directives flex-layout, je dois également créer cette div unique et ce serait bien si je pouvais les attacher directement à l'élément hôte au lieu d'avoir à le faire.

Ce serait super cool de pouvoir ajouter des directives dynamiquement telles que :

const msked = componentFactory.createDirective(MaskedInputDirective);
msked.textMaskConfig = {};
this.elementRef.directives.add(msked);

De plus, si je veux des directives flex-layout, je dois également créer cette div unique et ce serait bien si je pouvais les attacher directement à l'élément hôte au lieu d'avoir à le faire.

@tsteuwer Vous pouvez toujours utiliser le sélecteur :host dans votre scss pour appliquer des propriétés de style à l'élément hôte.

Mais oui, j'aimerais aussi pouvoir appliquer des directives à l'élément hôte. serait utile pour rendre l'élément hôte déroulant et appliquer CdkScrollable à partir de Angular Material CDK.

Wrapper tout dans le modèle de composants dans un modèle ng de niveau supérieur

Une alternative légèrement plus fluide consiste à utiliser https://github.com/trotyl/angular-contrib et à ajouter

host: { ngNoHost: '' }

Ce projet cale le moteur de rendu et rend les enfants des éléments avec l'attribut ngNoHost, sans parent.

Il a bien sûr beaucoup des mêmes inconvénients.

Dommage que ce soit toujours ouvert après 3 ans. Les directives liées à l'élément hôte amélioreraient vraiment la capacité de réutilisation du code.

De plus, si je veux des directives flex-layout, je dois également créer cette div unique et ce serait bien si je pouvais les attacher directement à l'élément hôte au lieu d'avoir à le faire.

@tsteuwer Vous pouvez toujours utiliser le sélecteur :host dans votre scss pour appliquer des propriétés de style à l'élément hôte.

Mais oui, j'aimerais aussi pouvoir appliquer des directives à l'élément hôte. serait utile pour rendre l'élément hôte déroulant et appliquer CdkScrollable à partir de Angular Material CDK.

Pas idéal mais vous pouvez créer le CdkScrollable par programmation de cette façon :
this.scrollable = new CdkScrollable(this.elementRef, this.scrollDispatcher, this.zone);
this.scrollable.ngOnInit();

Vous devez également le détruire manuellement :
if (this.scrollable) {
this.scrollable.ngOnDestroy();
}

https://github.com/angular/angular/issues/8785#issuecomment -361004682 IgorMinar le travail Ivy rend cela plus faisable. Mais oui après la v6.

@mhevery Suite à votre commentaire :point_up_2:, maintenant qu'Ivy a enfin complètement atterri, pouvons-nous assez s'il vous plaît avoir cette fonctionnalité à (ou avant) la sortie de la v10 ? Si ce n'est pas le cas, veuillez nous mettre à jour sur les autres considérations qui pourraient retarder cela davantage.

Y a-t-il des changements ?

Si cette fonctionnalité spécifique figurait sur l'enquête Angular https://twitter.com/angular/status/1252646001162088448?s=20 , je parie que ce serait l'entrée la plus votée.

Il y a des tonnes de fonctionnalités qui seraient les mieux votées, celle-ci bien sûr, mais aussi utilisant Observables pour @output et bien d'autres. Malheureusement, au rythme actuel, ils ne seront jamais mis en œuvre.

Si cette fonctionnalité spécifique figurait sur Angular Survey, je parie que ce serait l'entrée la plus votée.

Super idée @princemaple !

Bien que ce ne soit pas idéal, cela peut en fait être abordé dans la section « commentaires supplémentaires » de l'enquête (de la question 2)
Où il est dit:

"How else should we improve Angular for you?"

Donc, en gros, à tous ceux qui sont intéressés par cette fonctionnalité, veuillez simplement répondre au sondage et faire savoir explicitement que vous vous souciez beaucoup de voir le "problème n° 8785" mis en œuvre et résolu.

Voici le lien direct vers l'enquête :
https://goo.gle/angular-survey-2020

Que la force soit avec toi! ??

Moi aussi, j'ai eu du mal à ajouter plus de fonctionnalités aux composants par programmation, et honnêtement, je pense que certaines des propositions ici semblent être les MEILLEURES façons d'aborder ces problèmes spécifiques.

J'ai parlé avec des membres de l'équipe angulaire au sujet de cet article

Quelqu'un peut-il confirmer si c'est désormais possible avec Ivy ? Si oui, quelqu'un a-t-il un exemple ?

Comme aucun mot pour l'instant, j'ai pensé fournir la chose la plus proche que j'ai pu trouver, qui est un article d'il y a quelque temps sur la mise en œuvre des mixins avec Ivy : https://blog.nrwl.io/metaprogramming-higher-order-components -et-mixins-avec-angulaire-lierre-75748fcbc310

Et fondamentalement, on a donné l'impression qu'il s'agissait de piratage avec les composants internes d'angular, et qu'il n'était en fait pas conçu pour la consommation typique des utilisateurs.

Je ne sais pas s'il existe une raison technique qui nous empêche de pouvoir le faire, mais je pense que si nous avions les capacités de le faire, cela améliorerait considérablement mon quotidien avec angulaire.

« Nous avons considérablement augmenté notre investissement dans le travail avec la communauté. Au cours des trois dernières semaines, notre nombre de problèmes ouverts a diminué de plus de 700 problèmes dans le cadre, les outils et les composants. Nous avons abordé plus de 2 000 problèmes et nous prévoyons de faire d'importants investissements au cours des prochains mois, en travaillant avec la communauté pour en faire encore plus. — @StephenFluin
de l' annonce Angular 10

Donc je suppose que cela signifie que nous verrons ce problème annulé dans la v11 ? ??

Quoi de mieux pour « travailler avec la communauté » (et les apaiser) que de travailler sur l'ajout d'une de leurs fonctionnalités les plus demandées ! ? (celui-ci )

Écoute-les!

Juste pour définir les attentes, ce que vous demandez n'est pas une somme de travail insignifiante et les structures de données actuelles ne sont pas vraiment conçues pour cela. Donc, pour soutenir quelque chose comme ça, il faudrait une ingénierie majeure.

@mhevery en quoi est-ce différent de les appliquer à partir du parent dans le modèle ?

@k3nsei Il est nécessaire de le voir du point de vue de NgModule , qui est en fait l'élément clé qui crée l'infrastructure pour tous ses composants.

@mlc-mlapis Nous avons @HostBinding et @HostListener donc peut-être que @HostDirective serait un bon choix pour cette fonctionnalité. J'ai vu des discussions selon lesquelles Ivy apis permet de telles fonctionnalités.

Pour moi, le point clé est d'avoir une API de composition qui nous permettrait d'avoir plus de classes découplées avec la possibilité d'avoir des extensions/traits avec des fonctionnalités réutilisables. Par exemple, comme sélectionnable, extensible/réductible.

@k3nsei C'est possible, mais je ne sais pas si ce n'est pas trop dynamique, donc moins performant que les structures strictement statiques.

"Juste pour définir les attentes, ce que vous demandez n'est pas une somme de travail insignifiante et les structures de données actuelles ne sont pas vraiment conçues pour cela. Donc, prendre en charge quelque chose comme cela nécessiterait une ingénierie majeure." — https://github.com/angular/angular/issues/8785#issuecomment-654391378

Merci pour votre réponse rapide @mhevery.

Je pense que je parlerai au nom de la communauté en disant que ce n'est pas du tout perdu pour nous que ce sera un très gros défi. Si ce n'était pas le cas, je suis sûr que nous aurions maintenant créé des bibliothèques tierces qui y parviennent correctement (d'une manière ou d'une autre). [à ma connaissance il n'y en a pas].

De plus, cela va sans dire, mais veuillez nous faire savoir s'il existe des fruits à portée de main (ou autre) que nous pouvons aider à contribuer à cela.

Nous vous remercions sincèrement et apprécions votre communication sérieuse et espérons que nous continuerons à faire partie du dialogue sur ce dont nous avons besoin par rapport à ce qui est réaliste/pragmatique à ajouter.

Bien que je comprenne qu'Ivy rend cela plus facile qu'avant.

@mhevery

@IgorMinar le travail Ivy rend cela plus faisable. Mais oui après la v6.

Bien que je comprenne qu'Ivy rend cela plus facile qu'avant

Ma nouvelle compréhension est "plus facile" ne veut toujours pas dire "facile"

Ma nouvelle compréhension est "plus facile" ne veut toujours pas dire "facile"

Ivy: La chose sur laquelle vous avez passé deux ans et qui ne résout toujours aucun des problèmes angulaires les plus populaires.

Ivy: La chose sur laquelle vous avez passé deux ans et qui ne résout toujours aucun des problèmes angulaires les plus populaires.

@pauldraper Je suppose que nos problèmes ne sont pas leurs "problèmes", car celui-ci n'est même pas sur leur radar (voir la feuille de route https://angular.io/guide/roadmap).

Pour moi personnellement, je pense qu'il est temps pour moi de chercher ailleurs un projet qui n'est pas seulement open source mais un projet dont la direction la communauté (et les utilisateurs) ont une réelle influence.

@pauldraper Je suppose que nos problèmes ne sont pas leurs "problèmes", car celui-ci n'est même pas sur leur radar (voir la feuille de route https://angular.io/guide/roadmap).

@somombo Je suis déçu par le fait que ce problème soit toujours ouvert après toutes ces années, mais je ne peux pas être d'accord avec vous Le premier point de la feuille de route concerne explicitement la gestion des problèmes ouverts de github. Les énumérer tous sur la feuille de route n'aurait pas beaucoup de sens, n'est-ce pas ? Ce problème est l'un des plus votés (ou le plus voté) et j'espère qu'il sera enfin résolu.

Le premier point de la feuille de route concerne explicitement la gestion des problèmes de github ouverts. Les énumérer tous sur la feuille de route n'aurait pas beaucoup de sens, n'est-ce pas ? Ce problème est l'un des plus votés (ou le plus voté) et j'espère qu'il sera enfin résolu.

non, ce n'est qu'un vœu pieux, lisez à travers https://github.com/angular/angular/issues/5689 il n'y a absolument aucune indication qu'ils veulent s'attaquer à l'un des problèmes les plus votés, à part les "formes fortement typées" dans le futur

@pauldraper Je suppose que nos problèmes ne sont pas leurs "problèmes", car celui-ci n'est même pas sur leur radar (voir la feuille de route https://angular.io/guide/roadmap).

@somombo Je suis déçu par le fait que ce problème soit toujours ouvert après toutes ces années, mais je ne peux pas être d'accord avec vous Le premier point de la feuille de route concerne explicitement la gestion des problèmes ouverts de github. Les énumérer tous sur la feuille de route n'aurait pas beaucoup de sens, n'est-ce pas ? Ce problème est l'un des plus votés (ou le plus voté) et j'espère qu'il sera enfin résolu.

Tout de même .. j'ai fini d'attendre .. ce problème a littéralement été un énorme bloqueur pour moi. Donc, le fait qu'il ne semble même pas que cela soit prévu pour bientôt signifie qu'il est temps pour moi personnellement de passer à autre chose. Bonne chance à tous les autres.

J'aimerais que cela soit renommé en "Prise en charge de l'ajout de directives aux directives". Bien que ce nom puisse prêter à confusion, je pense qu'il est important que cette fonctionnalité fonctionne sur les directives et ne se limite pas aux composants. D'autres noms pour la fonctionnalité peuvent être "directives implicites" ou "directives attachées", ce qui signifie que lorsque vous utilisez un composant ou une directive donné dans un modèle, il extrait les directives implicites/attachées sur l'élément hôte.

J'ai voulu cela plusieurs fois, principalement parce que la composition est potentiellement une forme de réutilisation plus propre dans Angular, par rapport à l'héritage. L'héritage peut être maladroit car il n'y a pas d'héritage multiple, les paramètres du constructeur doivent être transmis et certaines fonctionnalités angulaires fonctionnent lorsqu'elles sont héritées, et d'autres doivent être "reconnectées" dans chaque classe feuille.

J'imagine que les "directives implicites/attachées" fonctionnent comme une forme d'instanciation de directive locale ou locale, ce qui entraîne l'instanciation de la directive sur l'élément hôte sans que le sélecteur de directive existe dans le balisage du modèle.

Voici un exemple :

@Directive({
  selector: 'app-popup',
  attachDirectives: [
    FocusAreaDirective
  ]
})
export class PopupDirective {

  // Attached directives can be injected, just like template-declared directives today
  constructor(public focusArea: FocusAreaDirective) {
  }

}

Les propriétés @Input() et @Output() de la directive jointe peuvent être utilisées dans le modèle, et les méthodes de cycle de vie de la directive jointe doivent être appelées dans le cadre du cycle de vie du composant hôte. La directive jointe peut également se lier à l'élément host. Fondamentalement, elle agit exactement comme une directive déclarée par un modèle aujourd'hui, mais n'a pas besoin d'être déclarée dans le modèle.

Je pense que cette fonctionnalité apporterait un avantage significatif à Angular, permettant des architectures de composants plus propres / plus simples via la composition de directives.

Aujourd'hui, vous avez 2 choix si vous souhaitez une forme similaire de réutilisation des directives :

  • Exiger qu'un ensemble de directives associées soit toujours déclaré ensemble dans le balisage du modèle ; et détecter et lancer des erreurs si les directives requises ne sont pas présentes dans le constructeur. Il n'y a aucun moyen d'exiger que les directives requises soient déclarées sur le même élément. C'est compliqué du point de vue de la création de modèles et de la documentation, et ce n'est pas une API ou un contrat solide en raison de la redondance, mais ce n'est pas horrible par ailleurs.
  • Instanciez manuellement les directives attachées dans la directive hôte et transférez les paramètres du constructeur, les propriétés @Input/ @Output , les liaisons hôte et les méthodes de cycle de vie aux directives internes. C'est un gâchis fragile pour les auteurs de composants, mais c'est faisable avec un ensemble simple de composants connexes. C'est beaucoup plus agréable pour la création de modèles.

En d'autres termes, l'absence de la fonctionnalité crée parfois un compromis inutile entre l'utilisation de composants propres + simples et la création de composants propres + simples.

@johncrim
Notez que dans un cas réel, votre directive personnalisée aurait des entrées, et vous voudriez les transformer et passer comme entrées à la directive jointe. Cela pourrait peut-être être fait avec une syntaxe similaire aux attributs host dans les options du décorateur Directive.

@amakhrov : Bon point - j'ai exclu les entrées de mon exemple pour plus de clarté. Dans la plupart des cas où j'en ai besoin, je n'ai pas besoin de transformer les entrées (ou sorties) pour les directives jointes - elles agissent (idéalement) comme des unités composables et leurs valeurs d'entrée (ou de sortie) pourraient être liées à partir du modèle en utilisant la directive parent (ou composant).

Dans les cas où il y a des conflits de nom ou des problèmes de clarté de nom (que j'essaierais d'éviter lors de la conception de directives pour la composition), ou lorsque les entrées ou les sorties doivent être transformées, cela pourrait être géré assez facilement en injectant la directive jointe dans le parent directive et créez de nouvelles propriétés d'entrée ou de sortie sur le parent qui délèguent aux directives jointes.

Je me suis trompé.
Ce problème est désormais répertorié dans la section « Avenir » de la feuille de route officielle. Voir https://angular.io/guide/roadmap#support -adding-directives-to-host-elements

Prise en charge de l'ajout de directives aux éléments hôtes

Une demande de fonctionnalité de longue date consiste à ajouter la possibilité d'ajouter des directives aux éléments hôtes. La fonctionnalité permettra aux développeurs d'augmenter leurs propres composants avec des comportements supplémentaires sans utiliser l'héritage. Le projet nécessitera des efforts substantiels en termes de définition des API, de sémantique et de mise en œuvre.

Comme je viens de le remarquer, je ne sais pas quand il a été ajouté, mais j'avoue que c'est une excellente nouvelle, et un geste significatif et rassurant. Je vais continuer à croiser les doigts.

Merci à l'équipe de l'avoir mis là ! ??

Cette page vous a été utile?
0 / 5 - 0 notes