Why are my component bindings undefined in its controller?

前端 未结 9 1778
醉梦人生
醉梦人生 2021-01-31 13:22

I\'m writing a simple angular component. I\'m passing a parameter as a binding and display its value on the screen. All works fine: I can see the parameter being displayed on th

相关标签:
9条回答
  • 2021-01-31 13:46

    There are two problems with the code causing the "undefined" error.

    1. As stated above the $onInit lifecycle hook should first be reached, the onInit is fired when all bindings have been made.

    From the official documentation:AngularJs Documentation

    $onInit() - Called on each controller after all the controllers on an element have been constructed and had their bindings initialized (and before the pre & post linking functions for the directives on this element). This is a good place to put initialization code for your controller.

    1. The second problem you will likely have, is that your controller will not reach the lifecyclehook when using "() =>" arrow notation as a parameter for the controller function.

    The problem being is that arrow notation won't have it's own scope, but rather use it's enclosing scope. Meaning that when using "this" will refer to the window object rather than the component. So calling this.$onInit() will be called on the window, and will not be fired, because it doesn't exist on the window.

    0 讨论(0)
  • 2021-01-31 13:51

    i will suggest some changes which you would really need to avoid these unusual bugs.

    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:'<p>{{$ctrl.myScopeObject}}</p>'
     }
    
    <test my-contact-id="8"></test>
    

    some points :

    1. passing bindings to a component in html is always going to be kebab cased ex my-contact-id and its respective javascript variable will be cammal cased : myContactId.

    2. if you are passing the value insted of the object use '@' in bindings. if you are using an object and passing the object to bindigs use '<. if you want 2-way-binding to that object use '=' in the bindings config

     bindings:{
          value:'@',
          object:'<', // also known as one-way
          twoWay:'='
        }
    
    0 讨论(0)
  • 2021-01-31 13:52

    The keyword this doesn't seem to works with arrow function, this works with

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

    When using arrow function, this, seems to refer to the window object because

    An arrow function does not create it's own this context, rather it captures the this value of the enclosing context

    0 讨论(0)
  • 2021-01-31 13:55

    For those using Directives, where Components are assumed, if bindings{} is specified it appears adding those same parameters to scope{} works:

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

    *Discovered after I wrote the above that an additional scope parameter, foo, wasn't available on $scope until I assigned it from $scope.resolve. So I had to do this in $scope.init(): $scope.foo = $scope.resolve.foo. Not sure why. Guessing it has to do with my UI Bootstrap Modal + Directives usage

    This may be obvious for others but wasn't for me being relatively new to AnguluarJS.

    My problem was using Directives with UI-Bootstrap Modals which are compatible with Directives but designed and documented for use with Components.

    0 讨论(0)
  • 2021-01-31 14:00

    The value for contactId is available on the $scope in your controller:

    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: "<div>Contact id from view: {{model.contactId}}</div>"
    });
    

    Link to another version of your Plunker here.

    0 讨论(0)
  • 2021-01-31 14:01

    Its maybe its not the best practice, but you have a easyer access to those values:

    $scope.$ctrl.contactId
    

    You can get all the bindings in the property $ctrl inside the $scope.

    I hope its help

    0 讨论(0)
提交回复
热议问题