ui-bootstrap modal scope bug - angularjs

I am noticing some weirdness with the ui-bootstrap modal scope. It seems that when using ng-model in it, you have to reference $parent to get to the scope of the modal controller. Notice in my plunker that the other properties such an ng-options doesn't require $parent:
http://plnkr.co/edit/xGSHz4EkZvGr2D6CUeBz?p=preview
Any idea why? I found a similar issue here:
Scope issues with Angular UI modal
That led me to try the $parent change but I am unable to comment on that thread because I don't have enough reputation.
Any idea why the scope seems to change?
Thanks!

The modal has its own scope (I've never used Angular UI, but it's the only thing that can be happening) and when you're setting "selectedLocation" the property is getting set on the modal's scope and not your controller's scope. The $parent is forcing it to got your controller's scope, but that's not a good solution because you'll be locking your self into a certain structure always assuming the parent of the modal has the "model".
Here's a modified Plunker using a model object on your controller scope (using model.selectedLocation)
http://plnkr.co/edit/B5kZaIA5xi2RediUTBK7?p=preview
Anyways, if you put your property on something like "$scope.model.selectedLocation" that changes the behavior. Now, when I reference "model.selectedLocation" on the modal, the modal's scope doesn't have a model object so Angular goes up the scope chain to your controller's scope (which does have a model object).
Watch this video from John Lindquist, I think it can explain it much better than I can. :-)
http://egghead.io/lessons/angularjs-the-dot

Related

AngularJs: Detect Click on Parent scope from isolated directive

Hi I have an isolated directive. I want to detect if the scope has been clicked on using $scope.$parent object. Is this possible. I am trying to listen to a click event on a parent scope using the scope object variable...is this possible?
In this particular instance, you would want to use $scope.$on to listen to the event occurring.
Todd Motto provides a great example to understand this in more detail.
https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

angular directive automatically re-instantiated when scope change

Many of my directive (soon to become components) takes their scope from variables set by other directives. Currently in each directive I have to watch my scope to know if it has changed which seems to complicate the code unnecessarily. So I started using ng-if="vm.ready" on my tag to reinstantiate the directive when I need it to. But then the management of that state is left outside of the directive which is harder to maintain.
I am wondering if angular provide such a mechanism when if the scope of your directive change then it will at least reinstantiate your directive controller.
Thanks
You can probably use $onInit()
After the controller is instantiated, the initial values of the isolate scope bindings will be bound to the controller properties. You can access these bindings once they have been initialized by providing a controller method called $onInit, which is called after all the controllers on an element have been constructed and had their bindings initialized.
https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L250

Ionic framework with AngularJs : Can a modal have the same controller as the view that launches the modal?

I am trying to build out a multistep form for a complex object. I use the modal to section out parts of the form. The Ionic examples I could find, appear to assign a different controller to the modal. I would like to keep the view plus all the modals it launches, all of them associated with one controller. Is that possible? I tried assigning to the modal view ng-controller="viewCtrl" where viewCtrl is also the controller of the starting view that launches the modal, but it appears to hang chrome with a high CPU which subsequently necessitates killing the chrome tab.(some sort of cyclic effect by calling the same controller??)
Your advice/insight would be welcome.
I assume that your modal is a directive.
I also assume that you have it placed inside the view (controller scope).
If the above are correct than the directive inherits the $scope properties and methods from the parent controller (a general thing in angular), unless your directive has an isolated scope (if you have the scope property in the directive set to anything but false).
If your directive has an isolated scope you can still pass data from the parent using attributes on the directive. If you want to pass something from the directive to the parent you can use $emit.
You can also access the parent from the directive using $parent but I would suggest against it.

When does controller come into play in AngularJS?

I am trying to understand the $scope and how controller and view are clued together. When Angular first runs through the DOM elements, when it finds ng-controller what does it do? I know when it finds the binding variables, it creates either watch or keydown events and also for the events it injects itself and watch for the other related events. It is done by creating a scope for that given DOM element. so when an item changes in view or model it can push the value to proper places. My question is when does controller is instantiated and $scope get injected into it and how $scope calls associated methods when a event happens?
Thanks
You would have to go through the documentation on their site for clarity. From what I understand when the framework encounters the ng-controller attribute on the view, it will attach and instantiate the controller. Any code directly within the controller function will run right there. If you want code to run only on certain events like a click event then you put ng-click='myFunction()' on the element and myFunction as a $scope property. If you want to run code inside a controller on some other event then you need to use $scope.$on within the controller and $scope.$broadcast to trigger the event outside. Note that controller should only have business logic. Any code to directly manipulate DOM goes within a Directive. Use scope property in the directive to bind variables and functions between the controller and the directive.
Again, as I said, it will help to go through documentation and videos on youtube to get a better understanding on the foundations of AngularJS.

AngularJS - nested directives without transclude?

Accompanying plunker.
I have an attribute-level custom directive in a div. The directive has an isolated scope. Inside my div I have other directives that expect to be in the scope of the parent.
The issue is that the directives inside my div have access only to the isolated scope, not to the parent scope. I understand why, but I'm not clear on how to solve it cleanly.
I know that I can use transclude to solve this (see plunker) but this feels very sloppy. I have no need for a template, but I'd have to create one just for transclude to work, and transclude seems to be the only way to ensure that my nested directives have access to the correct scope.
Is there an alternative, cleaner way to do this?
To head off some possible questions:
I'm using an attribute-level directive instead of an element-level to make things easier for IE
I'm using an isolated scope because it's a best practice - I don't want to hose my parent scope by accident, and I want the directive to be portable.
I'm really not sure what you're trying to do.
But what you're actually doing is leveraging bidirectional binds on an isolated scope for ill-effect. It almost seems unrelated to your question.
Anyhow... here is an update to your plunker
Basically what was happening is inside of your isolated directive you need to use whatever name you've assigned in your scope declaration, in this case toggleOn().
however if you want to you can do this. Basically just call $parent.colorToggle().
You can decide if this is "less sloppy" than transcluding:
<button ng-click="$parent.colorToggle()">Inside</button>
Isolate scopes have access to the parent scope via a $parent property. Although an isolate scope does not prototypically inherit from its parent scope, Angular still maintains a hierarchy via $parent and $$childHead and $$childTail.

Resources