angular ngClass evaluation - javascript

I've been learning AngularJs and have built a very basic Angular app. In one part of the app, I've used ngClass at a div element like
<div ng-class='{"some class": aFuncTruthyOrFalsy()}'>
<!-- aFuncTruthyOrFalsy() is defined in the controller for this view-->
Now, there's an input element in the view that is non-related to the above element and does not relate at all to any of the values checked in the function above.
I noticed that every whenever I type something in the input field (change event, keypressed event) it causes a re-evaluation of the ngClass. (I've put in a console log inside the aFuncTruthyOrFalsy function). I'm not able to determine which all events are bubbling to cause the reevaluation.
It seems to me that ngClass reevaluates at every single event in the page.
Can anyone please explain/elaborate this behavior?
Is it possible to cache the evaluated class at the initial load of the view?
What if there are multiple ngClass being used in the same view and each of the expression evaluation is delegated to some function that again does some multiple operation to come to get the evaluated expression?

Angular binding is using $watch to monitor changes in the function value. The digest cycle is calling your function to compare the result with last value.
This article is nice explaining this
http://tutorials.jenkov.com/angularjs/watch-digest-apply.html#watch
I suggest binding to scope variables instead of functions. i.e. have a variable in the scope that will store result of that function, and you update that whenever required.
after all you don't want to call methods from your view probably.Your current setup leaves the door open to make the whole MVC concept void,e.g. someone later add functionality inside that method that was supposed to be just a getter.

When something is changed in the scope AngularJS automatically triggers a $digest cycle by calling $digest(). When the $digest cycle starts, it fires each of the watchers.
Angular sets up a watcher on the scope model, which in turn updates the view whenever the model changes.
So when you change something in the scope, all the watchers are fired and the model is reevaluated.
Here is a good article on the topic: Link

You can do something like
<div ng-class="{'background1': color.back}">
<label> <span>{{emp.comp}}</span> </label>
</div>

Related

What is the best way to handle events in AngularJS in this case?

I am absolutly new in AngularJS and I have the following doubt about how to handle event in Angular.
So I know if in a view I have something like this:
<input type="text" ng-model="handle" />
it means that exist a 2 way binding between this input element in the dom and an handle variable into the Angular $scope, for example:
$scope.handle = '';
So any change that happen into this input object implies a change of the handle property in the $scope and vice-versa.
So, into the Angular applcation, I can explicitly declare a whatcher
// I explicitly declare a whatcher on the handle property: when the value of this propertu change the function() is performed:
$scope.$watch('handle', function(newValue, oldValue) {
console.info('Changed!');
console.log('Old:' + oldValue);
console.log('New:' + newValue);
});
So it should have the same meaning of manually adding a classic vanilla JavaScript EventListener (by the addEventListener() on the object that I want to observe in a classic old vanilla JavaScript application (that don't use Angular).
When something change on the input value the function associated to the whatcher is performed.
Ok it is pretty clear for me.
Now I say that I can also do something like this.
Into the HTML code I can have something like:
<input type="button" value="Click Me" ng-click="alertClick()" />
And in the Angular controller I will have something like:
$scope.alertClick = function() {
alert("Clicked !!!");
}
So it seems like the ng-Click directive perform a function that is a $scope field when there is the click event on the button.
But can I do the same operation as done in the first example? Can I do it declaring a whatcher on the button if it is associated to a model object by the ng-model="handle" directive?
When is better use the first method and when is better the second method to handle events in AngularJS?
ngModel is used to bind an imput form the UI to your controller
ngClick is just a regular javascript expression that have access to your controller scope that will be executed at the click event.
Here you have to use ng-click.
With angular a good practice is to avoid using function like addEventListener() or Jquery other function...
Because AngularJS wrap all this functionality and will run digest loop or other voodoo magic if necessary.
Use the click event. $scope.$watch should be used watching when something changes instead of things that are better for event handlers.
The tow "methods" you pointed out are not the same thing. At all.
The first, $watch, is intended to listen to the $scope changes. You can specify which property of the scope you want to watch, and when a change occur it will call you callback function. For more details, see the Digest cycle documentation.
The second, ng-click attribute directive, listen to the DOM events and evaluate the expression you pass in when the event occur.
In your case, for the button, you have two options. You can use the ng-click attribute directive to trigger a function in your scope OR use the ng-submit attribute directive in the form html tag of your inputs. That way you can trigger the form validation with the button or when the Enter is pressed.
See the documentation for ngSubmit.
ngModel applies to specific elements such as input,select, and textarea. As the result, you cannot use ngModel on a button. That is why you use ngClick to get the click event.

Change placeholder of input from angularjs directive wake scope model 'undefined'

So I have some trouble with my angularjs application. I try to implement a specific directive that make allow to translate my app easily. It works well on my text fields, but it doesn't work on input field to change my placeholder.
To be clear, here you can see some code sample :
http://plnkr.co/edit/GUS2FYCxA6wAOtkoxG66
$scope.validform = function() {
console.log($scope.valuefield);
};
As you can see, when i click on the button, my input model "valuefield" is "undefined". Or i want to see the value of the input.
What seems really strange for me is that the directive change the placeholder, but do not touch at the model.
I think I have to be more specific on the scope definition of the directive, or to use some $watch function but I am not sure how.
Can anyone guide me on this?
Ok, so finally it was pretty easy.
I only had to change my directive parameter from
scope : true
to
scope : false
By doing this, my directive is using the exact same scope than the controller. So The scope controller is not change and steal working as it should be.

CodeMirror going into infinite loop when implementing on change function

I need to track change in CodeMirror editor. So I implemented:
CodeMirrorInstance.on("change", function(CodeMirrorInstance){
$scope.onChangeFunc(CodeMirrorInstance);
} );
In onChangeFunc I do insert based on condition new value using
CodeMirrorInstance.setValue(newCode);
Apparently it leads to infinite loop. How to break this vicious circle?
setValue will always trigger another "change" event (it changes the content, after all). You'll have to make your change handler clever enough to not cause additional changes for changes you yourself caused. Looking at the origin property of the second argument passed to the "change" event handler might work -- it contains a sting that identifies the source of the change, which will be "setValue" when setValue was called.

Which event used in jquery when textbox value get changed using code not by manually?

I am developing a application in MVC.
I have a view which contain another partial view.
I have textbox1 in a parent view but its value get assigned from partial view.
Now, the moment the Textbox1 get assigned with some value, I want to perform some action
like put the 10% value textbox1 value on the another textbox, textbox2 of the view.
( I want the event when textbox value get changed by code, not the manual entry.
so cant use blur() event. )
which event in jquery should I used to perform this task ?
Partials views are all processed server-side, where Javascript is not executed. Javascript only works with the full page and does not know anything about partials, so take this worry out of your question.
As already been mentioned, you need .change() and if that is not good enough, just create a function that updates value of your checkbox and do other stuff which you need doing.
//psudo-code using .trigger()
function updateTextbox(value){
$('#myTexboxId').val(value);
$('#myTexboxId').trigger('change');
}
And here another method where you create another function that updates your values and does the calculation for you.
//pseudo-code using another function
function updateMyTextbox(value){
$('#myTextboxId').val(value);
doCalculation();
}
$('#myTextBoxId').on('change',function(){
doCalculation();
});
function doCalculation(){
// update your other values
}

AngularJS: Wait for ng-click event inside $scope function

All:
I have a function that is activated by an ng-click event. I want this function to wait on another ng-click event. The idea is to choose an action, and then choose a target for that action (via clickable objects in the DOM).
I'm not sure how to accomplish this. I know that I can use an Angular deferred event (using Q). However, how can I capture an ng-click event inside my original function without having to hold a reference to the deferred object within my scope?
Edit: The reason I'd like to design it this way is because I don't want my "targets" to perform any action on ng-click unless an action has been clicked; targets should only be selectable after an action has been selected.
If I understand your problem correctly, you can use the controller's $scope to keep track of this state information. E.g., in the ng-click function for an action, set a $scope.action property. In the ng-click function for the target, check that an appropriate $scope.action has been set.
If you have multiple targets, and you need to keep track an action for each one, use an array to keep track of which actions have been selected.

Categories