Material: bindToController and $onInit

Created on 7 Aug 2016  路  16Comments  路  Source: angular/material

Actual Behavior:

  • What is the issue? *
    I am using $mdDialog bindToController option with TypeScript classes transcompiled to es6. My locals are not getting bound to the controller. With es5 option, the locals are getting bound to the controller.
    Looking at the AngularJS documentation, they are depreciating binding to the controller before a constructor is being called (even for es5). As per the attached AngularJS discussion, this will be depreciated by AngularJS 1.6 (not a default option). So this will soon become a bug.
    https://github.com/angular/angular.js/issues/14206
    I am using $onInit function to initialize the controller bound values. This $onInit function is not getting called.
  • What is the expected behavior?
    $onInit function should be called when bindToController is set to true

CodePen (or steps to reproduce the issue): *

  • CodePen Demo which shows your issue:
  • Details:

Angular Versions: *

  • Angular Version: 1.5.8
  • Angular Material Version: v1.1.0-rc.5

Additional Information:

  • Browser Type: * Chrome
  • Browser Version: * 51.0.2704.103 m
  • OS: * Windows 10
  • Stack Traces:

Shortcut to create a new CodePen Demo.
Note: * indicates required information. Without this information, your issue may be auto-closed.

Do not modify the titles or questions. Simply add your responses to the ends of the questions.
Add more lines if needed.

required

Most helpful comment

So where do we stand with this?

My issues is that $onInit hook is not called when the controllers is used for mdDialog.

http://stackoverflow.com/questions/42676600

All 16 comments

Thanks for the issue, this is valid and we will fix that with #8474 and #8409

Also #8153 accounts for that issue.

@DevVersion - related to Component API support.

@DevVersion - status update on this ?

@DevVersion Hi. Has this been implemented in any version on NPM? We're using ES6 and can't get anything to pass into the $mdToast instance.

@mcblum We internally had a lot of discussion about this change in Angular, and we are planning to make our $mdCompiler more abstract and flexible (for the component API) in the future.

We don't have anything to show yet (sorry), but we will definitely move towards the component API soon.

In meanwhile if you can explain what specific issue you have? I might be able to help you with that.

@DevVersion Thank you! Basically I'm using ES6 / Webpack for the very first time and we want to do a $mdToast.show(). What we're finding is that the templateUrl doesn't work because everything is moved around once it's served and the locals aren't available in the template. I tried the following:

locals : {
   "message" : "Test message"
}

and then in the controller {{message}} and {{$ctrl.message}} and neither produced the message. Also, if we need actual functionality in this message, how would we give it its own controller?

@mcblum No problem. I think there is a bit confusion about the locals option.

The locals option does not provide bindings for the template, only for the controller instance.


See details for possible solutions

{
  locals : {
     "message" : "Test message"
  },
  controller: MyController
}
...

function MyController($scope, message) {
  // Provide the message in the scope.
  $scope.message = message;
}

But there is actually a more convenient way.

{
  locals : {
     "message" : "Test message"
  },
  controller: MyController,
  bindToController: true,
  controllerAs: '$ctrl'
}

function MyController() {}

Here is a demo: http://codepen.io/DevVersion/pen/RoraPK

Thank you @DevVersion! Does it change anything that I'm using ES6 syntax? I tried to copy your example and ended up with the error: controller is not using explicit annotation and cannot be invoked in strict mode. I tried using bindToController and it didn't error, but it also didn't bind. Here's what I did, sorry if it's stupid:

show(params) {
        let options = {
            template: `<md-toast>
                            <div class="md-toast-content" ng-class="$ctrl.type">
                                {{$ctrl.message}}
                                <md-button ng-click="hide()">Dismiss</md-button>
                            </div>
                        </md-toast>`,
            controller: toastController(),
            locals: {
                message: "test",
                title: params.title,
                classes: params.classes
            },
            controllerAs: '$ctrl',
            hideDelay: 50000,
            bindToController: true
        };

        this.$mdToast.show(options);

        function toastController() {

        }
    }

I should mention I also tried making toastController an ES6 class and importing it and such and then I got toastController not defined

I just encountered this issue too. We're using Typescript with target es6. Using bindToController and locals in $mdDialog does not attach anything to the controller from locals.

I made a pen to show it off clearly: http://codepen.io/anon/pen/LxxGZr

A workaround for now is to use DI with locals instead, but it would be great to have this working with ES2015 classes.

So where do we stand with this?

My issues is that $onInit hook is not called when the controllers is used for mdDialog.

http://stackoverflow.com/questions/42676600

@csvn Thanks so much for the pen! This is such a better way to use dialogs. Sadly you are right, this still does not work with your pen. But I happen to be using Typescript with jspm and a babel transpiler and it works beautifully.

I encountered a similar issue... I am not sure what the order of the digest cycle and initialization code is. I can tell $onInit is called correctly in my case but changes to variables I set (different from dialog locals) are not reflected in the UI.

To get it to work I had to introduced a hack to delay initialization code (of computed variables) using $timeout. I am using typescript as well. Just posting just in case this helps others until there is a fix...

this.$timeout( () => {
....                        
}, 100);

This should be fixed by fa997b9fcb5f8e1355a905bd0bb390da0514abb0, it just needs a release.

Actually, it has already been released in 1.1.5. Let's close it then!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robertmesserle picture robertmesserle  路  3Comments

ghost picture ghost  路  3Comments

reggiepangilinan picture reggiepangilinan  路  3Comments

buzybee83 picture buzybee83  路  3Comments

rdantonio picture rdantonio  路  3Comments