1

I have an application with the following controller:

var app = angular.module('someApp', []);
app.controller('mainCtrl', function($scope, $timeout) {
    $timeout(function() {
        $scope.myObject = {
            type: 'blaat'
        }
    }, 5000);
});

It has a timeout that creates an object with a type property on the mainCtrl after 5 seconds. I also have a component defined that takes a type property:

app.component('createSome', {
    templateUrl: 'create.html',
    controller: 'createController as create',
    bindings: {
        type: '='
    }
});

The component is rendered when the type on that object is available and the type is passed to that component:

<body ng-controller="mainCtrl">
    mainCtrl object: {{ myObject.type }}

    <create-some 
      ng-if="myObject.type"
      type="myObject.type">
    </create-some>
</body>

The controller of that component is creating a new object with that type on initialisation. This is where things go wrong; the object never gets the type property. I've also added an extra console.log when the createController is being initialised and don't see the type property there neither. The type is being printed correctly inside the component on the controller though.

app.controller('createController', function($scope) {
    var vm = this;

    console.log('creating create controller', vm.type);

    vm.newObject = {
        type: vm.type
    };
});

I guess this is some kind of timing problem; the controller is being initialised before the property of the component has been set on the scope of the controller. My question is: what do I have to change to get the object in the component controller to work as wanted. The only thing I can think of, but would rather avoid, is using a watch.

I've also created the following plunk containing all of the above:
https://plnkr.co/edit/XIfm1y6GBT2WcFKBvlPY

I'm asking this because I have a similar situation in an application I'm working on. The weird thing is that this seems to work fine in production on all environments. When running the code locally (using gulp with browserify) it fails on this on windows computers, but not on my macbook. Which kind of blows my mind. It worked on windows computers before and no code changes on that part happened in between. Would be even better if someone had an explanation for this, but I'm happy already with just the correct way to deal with it. :-) Besides the plunk is behaving the same on whatever machine I test it on, so it might be something specific to the rest of the project anyway.

1 Answer 1

1

By taking a look at the component documentation components bindings (vm.type in your case) are available after $onInit was called by the component - You are fine but you are a bit to early =). Please check this running plnkr. I don't know why it does work on some enviromnents for you but by reading the doc it should not work. Maybe you been lucky because your other hadware was much faster and vm.typewas parsed in the moment the component was instantiated.

var app = angular.module('someApp', []);

app.controller('mainCtrl', function($scope, $timeout) {
  $timeout(function() {
    $scope.myObject = {
      type: 'blaat'
    }
  }, 5000);
});

app.controller('createController', function($scope) {
  var vm = this;

  vm.newObject = {
    type: vm.type  
  }; 

  this.$onInit = function () {
    console.log('creating create controller', vm.type);
  };
});

app.component('createSome', {
  templateUrl: 'create.html',
  controller: 'createController as create',
  bindings: {
      type: '='
  }
})
Sign up to request clarification or add additional context in comments.

4 Comments

Wauw, "$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." should have ringed a bell, right?! Thank you very much!
@StefK Yep, this is the way you should do it =) $onInit FTW.
I really had no idea $onInit even existed. This was my first adventure using components. Very strange that it was working in my application in most situations though, because it looks indeed like it never should have, unless when being very lucky.
@StefK glad to help ya. Pushed ya a bit. ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.