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

$mdDialog: bindToController not working? Possibly needs more docs too #1534

Closed
epelc opened this issue Feb 16, 2015 · 11 comments
Closed

$mdDialog: bindToController not working? Possibly needs more docs too #1534

epelc opened this issue Feb 16, 2015 · 11 comments
Assignees
Milestone

Comments

@epelc
Copy link
Contributor

epelc commented Feb 16, 2015

I was trying to use $mdDialogs bindToController option but it doesn't appear to be working. I checked $scope.myLocal this.myLocal and $scope.ctrl.myLocal but none of them seem to be populated. I also logged the scope it didn't have anything related to my local objects.

I checked $scope.ctrl.myLocal because I found this test which appears to do that but it didn't work.

Also the docs on this are a bit vague they simply say the locals will be copied to the controller. Perhaps a demo using bindToController would be helpful.

Example trying to use `bindToController

$mdDialog.show({
            targetEvent: event,
            locals: {
                Invoice: {...} // I pass a var here
            },
            bindToController: true,
            controller: function($scope, $mdDialog) {
               // Nothing seems to have my invoice object
                console.log('Invoice:', this, $scope.Invoice, $scope.ctrl)
                $scope.done = function() {
                    $mdDialog.hide()
                }
            }
        })
@ThomasBurleson ThomasBurleson added this to the 0.8.0 milestone Feb 16, 2015
@ThomasBurleson
Copy link
Contributor

@rschmukler - wonder if a bug was introduced in 0.8-rc1....

@gkalpak
Copy link
Member

gkalpak commented Feb 16, 2015

It seems to work as expected using the latest master from bower-material (0.8.0-rc1-master-f704dda).
Demo fiddle

The issue seems to be that the locals are bound to the controller after its initialization. So, they are not present immediately, but they are there is you wrap the console.log into a timeout for example.
I am not sure how it used to work in previous versions, but the current behaviour seems reasonable.

@epelc
Copy link
Contributor Author

epelc commented Feb 16, 2015

@gkalpak Thanks I thought it would be available immediately

I think we just need some additions to the docs then.

@rschmukler
Copy link
Contributor

Indeed, the variables are not bound to the controller until after its instantiation. I will clarify the docs.

@mindmelting
Copy link

Would this not make more sense for them to be bound upon instantiation?

@xenit-raven
Copy link
Contributor

It would. Is it a choice or a limitation?

@mindmelting
Copy link

From what I can see in the source, it seems to be a limitation of the $controller syntax in angular which means they can't be bound before instantiation... see here... https://github.com/angular/material/blob/master/src/core/services/compiler/compiler.js#L118

@gkalpak
Copy link
Member

gkalpak commented Apr 23, 2015

BTW, it would be possible to have the bindings available upon "instantiation".

Angular does this for its directive controllers (with bindToController) using some private $controller API. Basically, it utilizes Object.create and SomeCtrl.apply (plus some extra housekeeping stuff).

(In an oversimplified version) I think it boils down to the following:

// Instead of
var ctrl = $controller(controller, locals);   // first instantiating the controller
angular.extend(ctrl, locals);   // then binding the values

// Do this:
var instance = Object.create(controller.prototype);
angular.extend(instance, locals);
controller.apply(instance, [/*any DI'ed values*/]);

@ThomasBurleson
Copy link
Contributor

@rschmukler - based on @gkalpak feedback, reopening to discuss for 0.10.

@ThomasBurleson ThomasBurleson modified the milestones: 0.10.0, 0.8.3 Apr 23, 2015
@rschmukler
Copy link
Contributor

@gkalpak thanks for poking the reinvestigation.

Turns out $controller has an (undocumented) argument (later) that makes it return a function that will be used to invoke the controller after wiring up the prototype chain. It then passes back the instance as a property of said function, giving us exactly what we need.

Another case where reading the source can often be the best solution.

Thanks!

@gkalpak
Copy link
Member

gkalpak commented May 5, 2015

Another case where reading the source can often be the best solution.

Angular is full of "easter-egg-ish", private (aka undocumented) APIs.
It definitely pays off to use the source, Luke 😄

Thx for fixing this !

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants