Is it possible to calculate and save local variable inside ng-repeat? - angularjs

i have a common block with ng-repeat:
<div ng-repeat="(position, task) in Tasks.plannedTasks">
{{(task.plan - (TasksTimeSpent[task.id][task.worker]).toFixed(2)}}
</div>
And now i need to set background if :
{{(task.plan - (TasksTimeSpent[task.id][task.worker]).toFixed(2)}} < 0
task.plan and task.worker can be changed and after this need to check if statement and change shown value
Is it possible to save expression result in variable (for example : curDif), display this variable and check variable inside if? I don't want calculate expression twice.
The way to calculate variable in controller is bad because variable is useless for application logic and need only for displaying but for using controller if task changes - i need to recalculate variable and use watcher for Task.

You can use ng-init for that:
<div ng-repeat="(position, task) in Tasks.plannedTasks">
<ng-init ng-init="curDif = (task.plan - (TasksTimeSpent[task.id][task.worker]).toFixed(2)">
{{curDif}}
</ng-init>
</div>

You may want to use ng-class as well to set the background.
<div ng-repeat="(position, task) in Tasks.plannedTasks">
<div ng-init="curDif = task.plan - (TasksTimeSpent[task.id][task.worker]).toFixed(2)" ng-class="'my-background':curDif < 0">
</div>
</div>
Then style your background using CSS.

Related

AngularJS How to set value of variable

I need to show/hide a tab based on the value of JSON, i.e. If the value of Region (In JSON, 'Region':'US') is equal to US in at least one of the items within JSON response I should show the tab, if not hide...
I'm using the following code to check if at least the item.region has US value, I'm able to read the values from the JSON but when I try to set the value to true to a variable inside the tag I don't get the value in the variable
<span ng-repeat="item in res.objects" ng-if="item.region === 'US'">
// Set myVariable = true
</span>
And after the variable has been set, display the div with ng-show and the value of the bool variable.
<div class="action-tab" ng-click="res.viewUS()" ng-show="<valueOfBoolVariable">
View US
</div>
Is this good approach to accomplish this? Any idea would be appreciated.
try using ng-init it allows you to evaluate an expression of your current scope
<span ng-repeat="item in res.objects" ng-if="item.region === 'US'">
<!-- Evaluate your variable -->
<div ng-init="evaluate(item)"> </div>
</span>
In your controller
$scope.evaluate = function(item){
//you do the job
}

Filter a directive by using a div wrapper or within the directive tag

I'm trying to go with the best approach and avoid unnecessary rendering/processing time in my AngularJS app when choosing between 2 directives to be displayed in the page inside an ngRepeat loop, want to know which is the best way:
If by setting the ng-if directly in the directive html element, like:
<div ng-repeat="element in list">
<my-directive-a ng-if="someFunction(element)"></my-directive-a>
<my-directive-b ng-if="!someFunction(element)"></my-directive-b>
</div>
Or by moving out the first <div> from the directive's template and use it as a wrapper for each directive. For instance:
<div ng-repeat="element in list">
<div ng-if="someFunction(element)">
<my-directive-a></my-directive-a>
</div>
<div ng-if="!someFunction(element)">
<my-directive-b></my-directive-b>
</div>
</div>
NOTE: The starting <div> element on each directive could be modified behave the same so I will basically take that out of the directive's html and moving it outside the directive declaration in order to place the ng-if there
What would be the best approach for this case? Are there any performance implications from doing it one way or another? Or is it just the same thing? Consider that the number of elements in the list could get really big.
They are quite the same, but you can improve performance with one-time binding, but only when element does not change at runtime (for example, let's say that it has property name, and your someFunction is like return element.name === 'John'). Angular just stop observing this function when it returns value, and watches will be deleted. There are 2 prerequisites to use this solution:
Elements properties in list does not change (if you rely on them in someFunction), for example if you rely on name property name must not change, because watcher on someFunction is note available.
When list changes or its elements properties change, you reload all list (for example, you fetch it from server again if you know that change occurred)
What you get with this? There is no watches after my-directives are drawn on ng-ifs, and when something changes, new reference is bound to list (for example, it comes from server) and everything will be redrawn, ng-ifs will run again and when will become stable (function returns value) then will be unbound. How it looks like? Like this:
<div ng-repeat="element in list">
<div ng-if="::(someFunction(element))">
<my-directive-a></my-directive-a>
</div>
<div ng-if="::(!someFunction(element))">
<my-directive-b></my-directive-b>
</div>
</div>
Two colons before expression. But be aware, that with one-time binding it's easy to mess up - you need to be sure that you test your code enough to be sure it works.

Is it possible to chain instructions in an ng-click?

I've got a couple of sliders I want to pick from a menu.
As a consequence, I need to both pick the right slider and reset the first slide to 0.
I have a slide model I set to 0 fro the ng-click just before opening the popup, but, unfortunately, slide is not reset to 0.
Any idea?
PS: I don't want to move the slide variable to the scope of the controller.
<div ng-init="slide = 0"></div>
<div
ng-repeat="s in sliders"
style="left:{{s.center.x - 70}}px; top:{{s.center.y}}px"
ng-click="slide = 0; openPopover('#slides-{{s.name}}')"
>
{{s.displayName}}
</div>
As long as it's a valid angularjs/js expression it will work
http://plnkr.co/edit/wta6GcVZHVccVbCf08IT?p=preview
<body ng-controller="MainCtrl">
<p ng-click="set = 'Cowa'; to = 'bunga!'; popup('test')">Hello {{name}}!{{set}}{{to}}</p>
</body>
As ng-repeat creates it's own scope, your current code will set slide to 0 inside these scopes. A quick (and maybe dirty) way is to use $parent to directly reference the parent-scope. E.g:
ng-click="$parent.slide = 0; openPopover('#slides-{{s.name}}')"

Can an Angular ng-mousover event trigger ng-style on multiple elements?

I'm currently learning Angular and I have a question.
I have two divs that change their background color on triggering the ng-mouseover directive. here is a little snippet of the two divs.
<div id="mid-left" class="col-lg-4">
<div class="row left-section" ng-repeat="variance in variances.variance_data" ng-style="background" ng-mouseover="background = setColor(variance)" ng-mouseleave="background = {}">
</div>
<div id="mid-right" class="col-lg-4">
<div class="row right-section" ng-repeat="variance in variances.variance_data" ng-style="background" ng-mouseover="background = setColor(variance)" ng-mouseleave="background = {}">
</div>
I assumed that the background variable I declared in the directives would be added to the existing $scope.
With the two divs being bound to the 'same variable' (in my mind) I assumed they would both change on when either ng-mouseover event was triggered.
Any and all help is highly appreciated.
Instead of background = setColor(variance), you should be defining a background variable in your local scope, and creating a function on the scope called setColor that alters the local scope background value. You'd then want to build a function to clear that value, as opposed to setting it to an empty object within your view.
ng-style takes..
Expression which evals to an object whose keys are CSS style names and
values are corresponding values for those CSS keys
I think it's impossible to say why it doesn't work without seeing what's returned from setColor(variance)

Possible bug using using ng-switch with Select tag in AngularJS

The Select tag I am using in conjunction with ng-switch does not properly display nor function properly after being set once.
<select ng-model="visuals" ng-options="visual for visual in visuals">
See JSFiddle:
http://jsfiddle.net/timothybone/UaFuc/3/
Thanks in advance!
:D
You should not bind visuals using ng-model as it is the list of items. Setting it replace the list value by the chosen item (which is a list of characters). Causing the strange behaviour.
<select ng-model="item" ng-options="visual for visual in visuals">
This new variable must be declared in the scope. It is also used to set an initial value:
$scope.item = 'none';
Your switch usage was also wrong, you need en enclose condition in the switching block.
<div ng-switch on="item">
<span ng-switch-when="lots">Youtube</span>
<span ng-switch-default></span>
</div>
If you want to set the content of the HTML using ng-bind-html-unsafe you should provide a variable as parameter (not sure how you could inject javascript that way).
<span ng-switch-when="lots" ng-bind-html-unsafe="youtube">Could not evaluate 'youtube' variable</span>
The span content is then replaced. Of course a new variable must be defined in the scope to hold the HTML content:
$scope.youtube = "<hr/>This is an HTML content<hr/>";
I updated the jsFiddle: http://jsfiddle.net/PMpLa/4/

Resources