AngularJS - Do I need to call $apply if no model is changed? - angularjs

Greetings Overflowers,
If I am changing an HTML native attribute (say a division's class) inside an event handler, do I need to wrap it with a call to $apply? In other words, are these native attributes watchable?
EXAMPLE:
I am doing a custom directive inside which I am modifying the element's classes for styling on certain events like mouse enter, but no modification to the scope (or model).
I am wondering if I need to surround this logic with a call to $apply just in case there is a $watch on these element's class attribute? Are these $watches possible using angularjs? My custom directive will be used by other programmers.
Kind regards

Any thing that Angular doesn't know about should be inside an $apply if you want bindings to be updated etc...
So no, this native attributes are not watchable if you manually change the DOM and it's not part of a user event or Angular's service event (like $http)

Related

Ng-if and custom directives

I've been creating custom directives that involve initialization of data on load. Since this initialization depends on the state of scope objects from the parent bound to the isolate scope within my directives, I've been enclosing the directives in ng-if statements, so they are only rendered in the DOM, and therefore initialized, once the appropriate parent scope objects are created.
Ng-if seems preferable because the directives have various API calls bound to $watches that I would prefer to not trigger until the data is valid.
For example, I have a directive that provides an interface for editing a scheduled event. The parent page allows users to select an event for editing, or to create a new event. Creating a new event is done in a way that allows the user to select a variety of values to pre-populate the event object with (start dates, event type, whether the event is tied to another object in the database, etc.).
The ng-if wrapping the directive gets set to true when the user makes the selections necessary for working with the event, and the event (either an existing event, for edits, or a framework for an event created by a custom service, for adds) is bound to the isolate scope of the directive.
This prevents the $watches from triggering until the valid event is bound to the directive, and also allows me to initialize some variables local to the directive for validation and data manipulation of the event.
The problem I'm running in to is that enclosing the directive in an ng-if isolates the isolate scope.
For example, a start time for the event is something that may, or may not, be specified by the user when they create the new event from the controller. If they don't, I want to calculate a default start time based upon other variables within the directive. If they do, then I want to use that value.
The way I'm doing this is to bind a scope variable from the controller to the isolate scope of the directive:
scope: {
editEvent: '=',
overrideTime: '='
}
This is passed as an attribute of my directive:
<add-edit-event ng-if="viewEdit" event="editEvent" override-time="overrideTime">
</add-edit-slot>
Once the directive creates the new event (or cancels out), I want to reset that overrideTime in the parent scope to null.
To do that from within my directive, however, I can't rely on the two-way binding to work without traversing up past the ng-if scope, thus:
scope.$parent.$parent.overrideTime = null;
I keep running into situations like this, where the fact that the directive is enclosed in an ng-if causes complications with the scope, which makes me feel like there's a problem with my general approach.
Is there a better way of handling conditional initialization and loading of custom directives, or is enclosing them in ng-if statements okay, so long as I deal with the interposing ng-if's scope appropriately?

Using/attaching ngChange directive from inside controller?

Total angular noob here, so perhaps a stupid question - is it possible to somehow use ngChange directive from inside controller, without defining it in the template?
What I really want is to be able to listen to user triggered change events on the inputs in the controller, but on my case, using $watch will not work because it will respond to all changes (whether they were made by the user or not).

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.

dynamically load interfaces, using angularJS: 2-way binding breaks

I'm trying to build web app that dynamically load interfaces, using angularJS.
I found that it was possible to bootstrap some portions of my code after the initial bootstrap of Angular (HTML template + Controller).
My problem is that, doing so, the 2-way data-binding doesn't work. See for yourself:
http://plnkr.co/edit/MtAWP6
Any idea? Am I seeking for something to do the wrong way?
Thanks!
Your problem isn't a bootstraping one (although you really shouldn't be using bootstrap to instantiate a controller, but rather $compile, imo - see this answer). It is a scope problem. You define a "mymodel" model in your controller, but then define it again in your form, for which angular automatically creates it's own scope. While the form's scope inherits from the parent scope, and thus seems to be "binding" the model, the inverse doesn't happen.
You need to either establish a binding between both scopes (or $watch the form's variable, or define the for in the surronding controller), or just assign the controller you want to the form, directly.
See your problem exposed here (see that while your $timeout changes both models, manually setting the model only changes one)
See it resolved here (by basically assigning your controller to the generated form, rather than to a enclosing div of said form)
I think maybe you should take another look at routing/ deep linking. You should be able to specify both a template url and a controller.
Check out this video
And the api docs

Resources