Composants AngularJS: les liaisons sont indéfinies dans le contrôleur

J’écris un composant angular simple. Je transmets un paramètre en tant que liaison et affiche sa valeur à l’écran. Tout fonctionne bien: je peux voir le paramètre affiché à l’écran.

Composant:

var app = angular.module("test", []); app.component("test", { bindings: { "contactId": " { //output: 'contact id from controller: undefined' console.log(`contact id from controller: ${this.contactId}`); }, template: "
Contact id from view: {{model.contactId}}
" });

Html:

  

Toutefois, lorsque j’essaie d’accéder à la liaison depuis le contrôleur (voir le fichier console.log), la valeur de liaison n’est undefined . Je ne comprends pas comment il peut être disponible dans la vue, mais pas dans le contrôleur.

Qu’est-ce que je fais mal?

Voici un plnkr illustrant le problème.

    Lorsque vous utilisez des composants angulars, il existe un point où le contrôleur n’a pas été connecté via la liaison interne. Si vous essayez de faire cela dans le constructeur de votre contrôleur, vous n’avez pas été lié aux liaisons. L’API Composante expose quelques crochets de cycle de vie que vous pouvez définir et qui se déclencheront à certains moments. Vous recherchez le hook $onInit .

    $ onInit () – Appelé sur chaque contrôleur après que tous les contrôleurs d’un élément aient été construits et que leurs liaisons ont été initialisées (et avant les fonctions de liaison pré et post pour les directives sur cet élément). C’est un bon endroit pour mettre le code d’initialisation pour votre contrôleur.

    par docs – https://docs.angularjs.org/guide/component

    Assurez-vous d’utiliser des tirets pour les liaisons en HTML et camelCase pour les liaisons en Javascript.

     app.component("test", { bindings: { "myContactId": "<" } }  

    C’est ce que j’oublie toujours de faire.

    La valeur de contactId est disponible dans la $scope de votre contrôleur:

     var app = angular.module("test", []); app.component("test", { bindings: { "contactId": "<" }, controllerAs: "model", controller: ($scope) => { var model = $scope.model; alert(`contact id from controller: ${model.contactId}`); }, template: "
    Contact id from view: {{model.contactId}}
    " });

    Lien vers une autre version de votre Plunker ici .

    Le mot clé cela ne semble pas fonctionner avec la fonction flèche, cela fonctionne avec

     controller: function() { alert('contact id from controller: ' + this.contactId); } 

    Lorsque vous utilisez la fonction flèche, cela semble faire référence à l’object fenêtre car

    Une fonction flèche ne crée pas son propre contexte, elle capture plutôt cette valeur du contexte englobant

    Je suggérerai des modifications dont vous auriez besoin pour éviter ces bugs inhabituels.

     app.component("test", { bindings: { "myContactId": "<" }, controller:function(){ var self=this; this.$onInit=function(){ // do all your initializations here. // create a local scope object for this component only. always update that scope with bindings. and use that in views also. self.myScopeObject=self.myContactId } }, template:'

    {{$ctrl.myScopeObject}}

    ' }

    Des points :

    1. passer des liaisons à un composant dans HTML sera toujours kebab cased ex my-contact-id et sa variable javascript respective sera cammal cased: myContactId.

    2. Si vous passez la valeur insted de l’object, utilisez ‘@’ dans les liaisons. Si vous utilisez un object et que vous passez l’object à bindigs, utilisez ‘<. si vous voulez une liaison bidirectionnelle à cet objet, utilisez '=' dans la configuration des liaisons

      bindings:{ value:'@', object:'<', // also known as one-way twoWay:'=' } 

    C’est peut-être pas la meilleure pratique, mais vous avez un access plus facile à ces valeurs:

     $scope.$ctrl.contactId 

    Vous pouvez obtenir toutes les liaisons dans la propriété $ ctrl à l’intérieur de $ scope.

    J’espère que son aide

    Pour ceux qui utilisent des directives, où les composants sont pris en compte, si des liaisons {} sont spécifiées, il apparaît que ces mêmes parameters sont ajoutés aux travaux de la scope {}:

     /*bindings: { modalInstance: '<', resolve: '<' },*/ scope: { modalInstance: '<', resolve: '<' }, 

    * Découvert après avoir écrit ce qui précède qu'un paramètre de scope supplémentaire, foo, n'était pas disponible sur $ scope tant que je ne l'ai pas assigné depuis $ scope.resolve. Je devais donc faire ça dans $ scope.init (): $ scope.foo = $ scope.resolve.foo. Pas certain de pourquoi. Je suppose que cela a à voir avec mon utilisation de l'interface utilisateur Bootstrap Modal + Directives

    Cela peut être évident pour les autres, mais ce n’est pas pour moi que je suis relativement nouveau à AnguluarJS.

    Mon problème était d'utiliser des directives avec des modaux UI-Bootstrap compatibles avec les directives, mais conçues et documentées pour être utilisées avec des composants.