angularjs execute expression from variable - angularjs

How to execute expression from variable?
I need something like formula which depends from another inputs.
For example my data:
$scope.items = [{
name: 'first',
formula: '',
value: 1,
type: 'text',
},{
name: 'second',
formula: '',
value: 2,
type: 'text',
},{
name: 'third',
formula: '{first}+{second}',
type: 'formula',
}];
and my view:
<ul>
<li ng-repeat="item in items">
<div ng-switch on="item.type">
<div ng-switch-when="text">
<input type="text" ng-model="item.value" name="{{item.name}}">
</div>
<div ng-switch-when="formula">
<span>{{item.formula}}</span>
</div>
</div>
</li>
I want that the result was 3
But it's {first}+{second} ofcourse

<div ng-switch-when="formula">
<span>
{{getFormulaResult(item.formula)}}
</span>
</div>
Controller method:
$scope.getFormulaResult = function(formula){
var formulaSplits = formula.split("+");
var left = formulaSplits[0];
left = left.substr(1);
left = left.substring(0, left.length-1);
var right = formulaSplits[1];
right = right.substr(1);
right = right.substring(0, right.length-1);
var sum = 0;
for(var i = 0; i < $scope.items.length; i++){
if($scope.items[i].name == left || $scope.items[i].name == right){
sum = sum + parseInt($scope.items[i].value, 10);
}
}
return sum || 0;
}

Related

How to programmatically check checkbox with dynamic model name?

I have created a some checkboxes with dynamic model name like this:
<label ng-repeat="item in main.itemDetails">
<input type="checkbox" checklist-value="item.price"
ng-click="itemChanged(item)" ng-model="checkboxes[item.name]">
{{item.name}} - <b>{{item.price}} €</b>
<br>
</label>
In my controller, I want to check some checkboxes if their model's name exists in array $scope.selectedItems.
I'm trying to do something like this but it isn't working:
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope['selectedItems[i].name'].isChecked = true;
}
for example if item.name = 'Item1' I want the model to be named $scope.Item1 and later I want to call $scope.Item1.isChecked = true;
What Am I doing wrong here?
Your are storing the model in the $scope.checkboxes, so you can set its value to true like the code below.
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope.checkboxes[$scope.selectedItems[i].name] = true;
}
It looks like your using a string literal here:
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope['selectedItems[i].name'].isChecked = true;
}
Just change this to read:
for (var i = 0, j = $scope.selectedItems.length; i<j; i++) {
$scope[selectedItems[i].name].isChecked = true;
}
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.main = [{
'name':'test1',
'price':'23',
'isChecked':false
},
{
'name':'test2',
'price': '25',
'isChecked':false
},
{
'name':'test3',
'price': '21',
'isChecked':false
}];
$scope.selectedItems = [{
'name':'test1'
},
{
'name':'test2'
}];
angular.forEach($scope.main, function(valueMain){
angular.forEach($scope.selectedItems,function(valueSelected){
if(valueMain.name=== valueSelected.name){
valueMain.isChecked = true;
}
})
});
$scope.toggleCheck = function(item){
if(item.isChecked === true){
item.isChecked === false;
}else{
item.isChecked === true;
};
}
}
<script src="https://code.angularjs.org/angular-1.0.1.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<label ng-repeat="item in main">
<input type="checkbox" ng-model="item.isChecked" ng-checked="item.isChecked" ng-change="toggleCheck(item)">
{{item.name}} - <b>{{item.price}} €</b>
<br>
</label>
</div>
</div>
Angular Foreach is the easiest way to solve this kind of problem.

AngularJs- Calculation inside a controller

Hello I want to be able to calculate some numbers inside a controller that contains elements. This is what have tried (ionic APP too btw) :
.controller('tasksCtrl', function($scope) {
$scope.tasksCollection = [
{ info: 'Go studying', measured: 'no', total: 1, done: 1, id: 1 },
{ info: 'Go to the beach', measured: 'no', total: 1, done: 1, id: 2},
{ info: 'Run', measured: 'yes', total: 30, done: 15, id: 3}
];
$scope.calculateProductivity = function(){
var total = 0;
for(var i = 0; i < $scope.tasksCollection.length; i++){
var product = $scope.tasksCollection[i];
total += (tasksCollection.done / tasksCollection.total);
}
return total;
};
})
and the page has:
<div class="item tabs tabs-secondary tabs-icon-left">
<div ng-app="starter" ng-controller="tasksCtrl" class="tab-item tab-main-left">
<span class="title-red"> {{ calculateProductivity() }} </span><span class="medium-text">Productivity Ratio</span>
</div>
<div class="tab-item tab-main-right">
<span class="title-red">20 </span><span class="medium-text">PMoney</span>
</div>
</div>
On the output I only see "{{ calculateProductivity() }}" and not the result, but if I write tasksCollection.info it gets correctly displayed.
thanks!
you are calculating total as:
total += (tasksCollection.done / tasksCollection.total);
and it should probably be:
total += (product.done / product.total);
PLease see this: http://stackoverflow.com/questions/20942878/angularjs-use-a-function-in-a-controller-to-return-data-from-a-service-to-be-use
The following changes should work:
<span class="title-red"> {{ productivity_ratio }} </span><span class="medium-text">Productivity Ratio</span>
for(var i = 0; i < $scope.tasksCollection.length; i++){
var product = $scope.tasksCollection[i];
total += (tasksCollection.done / tasksCollection.total);
}
$scope.productivity_ratio = total;

How to use the value in ngRepeat as a dynamic way to access a scope?

I have a set of value that I would like to dynamically generate in my view. How can I go about doing it in the following way?
$scope.mainKeyMapping = [
{
name: 'category1',
otherThings: ''
},
{
name: 'category2',
otherThings: ''
},
{
name: 'category3',
otherThings: ''
},
{
name: 'category4',
otherThings: ''
},
{
name: 'category5',
otherThings: ''
}
];
$scope.category1 = {something....}
$scope.category2 = {something....}
$scope.category3 = {something....}
$scope.category4 = {something....}
$scope.category5 = {something....}
HTML
<div ng-repeat="cat in mainKeyMapping">
{{category1}} // outputs obj
{{cat.name}} // outputs string "category1" <----- how do I output the obj?
</div>
First, put your categories into a collection:
$scope.categories = {
category1: {something....},
category2: {something....}
};
Now simply access the right category in your html:
<div ng-repeat="cat in mainKeyMapping">
{{categories.category1}} // outputs obj
{{categories[cat.name]}} // outputs obj
</div>

AngularJS checkbox filter directive

I have a AngularJS directive that allows users to select a values from a list to filter on. Pretty simple concept which is represented here:
Problem is when I click one of the checkboxes they all select unintended. My directive is pretty simple so I'm not sure why this is happening. The code around the selection and checkboxes is as follows:
$scope.tempFilter = {
id: ObjectId(),
fieldId: $scope.available[0].id,
filterType: 'contains'
};
$scope.toggleCheck = function (id) {
var values = $scope.tempFilter.value;
if (!values || !values.length) {
values = $scope.tempFilter.value = [];
}
var idx = values.indexOf(id);
if (idx === -1) {
values.push(id);
} else {
values.splice(idx, 1);
}
};
$scope.valuesListValues = function (id) {
return $scope.available.find(function (f) {
return f.id === id;
}).values;
};
and the data resembles:
$scope.available = [{
id: 23,
name: 'Store'
values: [
{ id: 124, name: "Kansas" },
{ id: 122, name: "Florida" }, ... ]
}, ... ]
the view logic is as follows:
<ul class="list-box">
<li ng-repeat="val in valuesListValues(tempFilter.fieldId)">
<div class="checkbox">
<label ng-click="toggleCheck(val.id)">
<input ng-checked="tempFilter.value.indexOf(val.id) === -1"
type="checkbox"> {{val.name}}
</label>
</div>
</li>
</ul>
First off, it toggleCheck fires twice but populates the correct data ( second time given my code it removes it though ).
After the second fire, it checks all boxes... Any ideas?
Perhaps its that the local variable doesn't get reassigned to the property of the scope property used in the view. Since your values are then non-existent and not found, the box is checked.
$scope.tempFilter.value = values
I took the interface concept you were after and created a simpler solution. It uses a checked property, found in each item of available[0].values, as the checkbox model. At the top of the list is a button that clears the selected items.
JavaScript:
function DataMock($scope) {
$scope.available = [{
id: 23,
name: 'Store',
values: [{
id: 124,
name: "Kansas"
}, {
id: 122,
name: "Florida"
}]
}];
$scope.clearSelection = function() {
var values = $scope.available[0].values;
for (var i = 0; i < values.length; i++) {
values[i].checked = false;
}
};
}
HTML:
<body ng-controller="DataMock">
<ul class="list-box">
<li>
<button ng-click="clearSelection()">Clear Selection</button>
</li>
<li ng-repeat="val in available[0].values">
<div class="checkbox">
<label>
<input ng-model="val.checked"
type="checkbox" /> {{val.name}}
</label>
</div>
</li>
</ul>
</body>
Demo on Plunker
The repeat that I used to grab the values based on the id, was the problem area.
<li ng-repeat="val in valuesListValues(tempFilter.fieldId)">
removing that and simple listening and setting a static variable resolved the problem.
$scope.$watch('tempFilter.fieldId', function () {
var fId = $scope.tempFilter.fieldId;
if ($scope.isFieldType(fId, 'valuesList')) {
$scope.valuesListValues = $scope.valuesListValues(fId);
}
}, true);
});
and then in the view:
ng-repeat="value in valuesListValues"

Check-all checkbox is not changes object properties from select

My Code - Plunker
I'm trying to changes status of all my list objects by using a master checkbox that
checks all objects and changes their properties by selecting the required status from the
select element.
The problem is that when I'm trying to apply change on all elements by using the "Check All" 'checkbox' it is not working.
e.g.
When I check manually all the checkboxes without using the master checkbox it is working.
My Code
var webApp = angular.module('webApp', []);
//controllers
webApp.controller ('VotesCtrl', function ($scope, Votes) {
$scope.votes = Votes;
$scope.statuses = ["Approved","Pending","Trash","Spam"];
$scope.expand = function(vote) {
console.log("show");
$scope.vote = vote;
$scope.ip = vote.ip;
$scope.date = vote.created;
};
$scope.change = function() {
for(var i = 0; i < $scope.votes.length; i++) {
if($scope.votes[i].cb) {
$scope.votes[i].status = $scope.votes.status;
$scope.votes[i].cb = false;
}
$scope.show = false;
}
};
});
//services
webApp.factory('Votes', [function() {
//temporary repository till integration with DB this will be translated into restful get query
var votes = [
{
id: '1',
created: 1381583344653,
updated: '222212',
ratingID: '3',
rate: 5,
ip: '198.168.0.0',
status: 'Pending',
},
{
id: '111',
created: 1381583344653,
updated: '222212',
ratingID: '4',
rate: 5,
ip: '198.168.0.1',
status: 'Spam'
},
{
id: '2',
created: 1382387322693,
updated: '222212',
ratingID: '3',
rate: 1,
ip: '198.168.0.2',
status: 'Approved'
},
{
id: '4',
created: 1382387322693,
updated: '222212',
ratingID: '3',
rate: 1,
ip: '198.168.0.3',
status: 'Spam'
}
];
return votes;
}]);
My HTML
<body ng-controller='VotesCtrl'>
<div>
<ul>
<li class="check" ng-click=>
<input type="checkbox" ng-model="master"></input>
</li>
<li class="created">
<a>CREATED</a>
</li>
<li class="ip">
<b>IP ADDRESS</b>
</li>
<li class="status">
<b>STATUS</b>
</li>
</ul>
<ul ng-repeat="vote in votes">
<li class="check">
<input type="checkbox" ng-model="vote.cb" ng-checked="master"></input>
</li>
<li class="created">
{{vote.created|date}}
</li>
<li class="ip">
{{vote.ip}}
</li>
<li class="status">
{{vote.status}}
</li>
</ul>
</div>
<br></br>
<div class="details">
<h3>Details:</h3>
<div>DATE: {{date|date}}</div>
<div>IP: {{ip}}</div>
<div>STATUS:
<select ng-change="change()" ng-init="votes.status='Approved'"
ng-model="votes.status"
ng-options="status for status in statuses">
</select>
<p>{{vote.status|json}}</p>
</div>
</div>
</body>
Why is master checkbox not working?
I changed your method change a bit to make it work.
From Plunker you can see that on master change all children still have old value. So I added onMasterChange method
HTML
<input type="checkbox"
ng-model="master"
ng-change="onMasterChange(master)"></input>
I created as default: $scope.master = false;
....
$scope.master = false;
$scope.onMasterChange = function(master){
for(var i = 0; i < $scope.votes.length; i++) {
$scope.votes[i].cb = master;
}
};
$scope.change = function(value) {
for(var i = 0; i < $scope.votes.length; i++) {
//if($scope.votes[i].cb == undefined){
// $scope.votes[i].cb = false;
// }
if($scope.master == true){
$scope.votes[i].cb = $scope.master;
$scope.votes[i].status = value;
}
else if( $scope.votes[i].cb == true) {
$scope.votes[i].status = value;
}
}
};
See Plunker
Hope it will help,
It is working, but I believe ng-model is taking precedence over ng-checked. If you remove ng-model from the checkboxes, ng-checked is working as expected.
<input type="checkbox" ng-checked="master"></input>
http://plnkr.co/edit/q35JlhOVSGxmu6QW8e98?p=preview
It is important to note, however, that ng-checked does not update your model, it only changes the presentation of the checkbox. A way of tackling this would be to remove the master binding, and call a method with ng-click on your master checkbox which changes .cb on each box.
Edit: Working version using a watch on the master checkbox.
http://plnkr.co/edit/3NwGtp1FX8g9bfMrbWU5?p=preview

Resources