Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

bindToController and $onInit #9259

Closed
prasannapattam opened this issue Aug 7, 2016 · 16 comments
Closed

bindToController and $onInit #9259

prasannapattam opened this issue Aug 7, 2016 · 16 comments
Assignees
Labels
P2: required Issues that must be fixed.
Milestone

Comments

@prasannapattam
Copy link

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.
    Properties set before constructor is called when using bindToController angular.js#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.

@devversion
Copy link
Member

devversion commented Aug 8, 2016

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

@ThomasBurleson ThomasBurleson reopened this Aug 9, 2016
@ThomasBurleson ThomasBurleson self-assigned this Aug 9, 2016
@devversion
Copy link
Member

Also #8153 accounts for that issue.

@ThomasBurleson
Copy link
Contributor

@devversion - related to Component API support.

@ThomasBurleson
Copy link
Contributor

@devversion - status update on this ?

@ThomasBurleson ThomasBurleson modified the milestones: 1.1.3, - Backlog Sep 10, 2016
@ThomasBurleson ThomasBurleson removed their assignment Sep 10, 2016
@mcblum
Copy link

mcblum commented Nov 9, 2016

@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.

@devversion
Copy link
Member

@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.

@mcblum
Copy link

mcblum commented Nov 10, 2016

@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?

@devversion
Copy link
Member

devversion commented Nov 10, 2016

@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

@mcblum
Copy link

mcblum commented Nov 17, 2016

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() {

        }
    }

@mcblum
Copy link

mcblum commented Nov 17, 2016

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

@csvn
Copy link

csvn commented Jan 18, 2017

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.

@ThomasBurleson ThomasBurleson self-assigned this Mar 7, 2017
@lucasmaj
Copy link

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

@j-walker23
Copy link

j-walker23 commented Sep 8, 2017

@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.

@henrymana
Copy link

henrymana commented Sep 15, 2017

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);

@mgol
Copy link
Member

mgol commented Sep 18, 2017

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

@mgol
Copy link
Member

mgol commented Sep 18, 2017

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P2: required Issues that must be fixed.
Projects
None yet
Development

No branches or pull requests

9 participants