I have a view model containg an object that is used to display some checkboxes:
components = {
"ComponentInfos": [
{
"Id": "1abb0ee5-7e44-4e45-92da-150079066e99",
"FriendlyName": "Component1",
"LimitInfos": [
{
"Id": "4b7cd37a-2378-4f4f-921b-e0375d60d19c",
"FriendlyName": "Component1 Full",
},
{
"Id": "ff9ebe78-fbe4-4a26-a3df-6ec8e52cd0f2",
"FriendlyName": "Component1 Light",
}
]
}
I am able to create the checkboxes with FriendlyName as label:
<h4>{{l.FriendlyName}}</h4>
<div>
<div ng-repeat="limitinfo in l.LimitInfos">
<label>
<input type="checkbox" ng-model="vm.settings.ComponentInfos[limitinfo.Id]"
value="{{limitinfo.Id}}"/> {{limitinfo.FriendlyName}}
</label>
</div>
</div>
I want to store the selected LimitInfo.Id in an array for each selected checkbox. I was able to store them in an object like this:
settings = {
"ComponentInfos" : {}
};
Result example:
"2e80bedb-4a18-4cc4-bdfd-837ffa130947": true,
"add1edf8-4f11-4178-9c78-d591a6f590e3": true
What I do need is to store the LimitInfo.Idin an array like this:
settings = {
"ComponentInfos" : []
};
Expected result:
"2e80bedb-4a18-4cc4-bdfd-837ffa130947", "add1edf8-4f11-4178-9c78-d591a6f590e3"
I uploaded my code to Plunker.
you can use a ng-click method on the checkbox with a custom controller method to push to that array.
<input type="checkbox" ng-model="vm.settings.ComponentInfos[limitinfo.Id]"
value="{{limitinfo.Id}}" ng-click="toggleSelection(limitinfo.ImpliedLimits)"/>
$scope.toggleSelection = function toggleSelection(item) {
var idx = $scope.vm.settings.ComponentInfos.indexOf(item);
if (idx > -1) {
$scope.vm.settings.ComponentInfos.splice(idx, 1);
}
else {
$scope.vm.settings.ComponentInfos.push(item[0]);
}
};
see this plnkr.
see this answer
One line solution
You can do the following in vanilla JS (ES5 and above, so modern browsers)
var data = {
"a": true,
"b": false,
"c": true,
"d": false,
"e": true,
"f": true
}
var arr = Object.keys(data).filter( key => !!data[key] );
// ['a', 'c', 'e', 'f']
Demo by directive:
var app = angular.module('plunker', []);
app.directive('myCheckbox',function(){
return {
restrict:'EA',
template:'<label>'
+'<input type="checkbox" ng-model="model" ng-change="toggleModel()" /> {{label}}'
+'</label>',
replace: true,
scope:{
label:'#',
value:'#',
output:'='
},
link:function(scope,elements,attrs){
//init checked status
scope.model=scope.output.indexOf(scope.value) > -1;
//binding click replace watch model
scope.toggleModel = function(){
if(scope.model){
scope.output.push(scope.value);
return false;
}
scope.output.splice(scope.output.indexOf(scope.value),1);
}
}
}
});
function MyViewModel()
{
this.components = {
"ComponentInfos": [
{
"Id": "1abb0ee5-7e44-4e45-92da-150079066e99",
"FriendlyName": "Component1",
"LimitInfos": [
{
"Id": "4b7cd37a-2378-4f4f-921b-e0375d60d19c",
"FriendlyName": "Component1 Full",
"ImpliedLimits": [
"ff9ebe78-fbe4-4a26-a3df-6ec8e52cd0f2"
]
},
{
"Id": "ff9ebe78-fbe4-4a26-a3df-6ec8e52cd0f2",
"FriendlyName": "Component1 Light",
"ImpliedLimits": [
"4f74abce-5da5-4740-bf89-dc47dafe6c5f"
]
},
{
"Id": "4f74abce-5da5-4740-bf89-dc47dafe6c5f",
"FriendlyName": "Component2 User",
"ImpliedLimits": []
}
]
},
{
"Id": "ad95e191-26ee-447a-866a-920695bb3ab6",
"FriendlyName": "Component2",
"LimitInfos": [
{
"Id": "8d13765a-978e-4d12-a1aa-24a1dda2149b",
"FriendlyName": "Component2 Full",
"ImpliedLimits": [
"4f74abce-5da5-4740-bf89-dc47dafe6c5f"
]
},
{
"Id": "2e80bedb-4a18-4cc4-bdfd-837ffa130947",
"FriendlyName": "Component2 Light",
"ImpliedLimits": [
"4f74abce-5da5-4740-bf89-dc47dafe6c5f"
]
},
{
"Id": "add1edf8-4f11-4178-9c78-d591a6f590e3",
"FriendlyName": "Component2 Viewer",
"ImpliedLimits": [
"4f74abce-5da5-4740-bf89-dc47dafe6c5f"
]
}
]
}
]
};
this.settings = {
"ComponentInfos" : ["4b7cd37a-2378-4f4f-921b-e0375d60d19c","2e80bedb-4a18-4cc4-bdfd-837ffa130947"]
};
}
app.controller('MainCtrl', function($scope) {
$scope.vm = new MyViewModel();
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.3.x" src="https://code.angularjs.org/1.3.20/angular.js" data-semver="1.3.20"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="l in vm.components.ComponentInfos">
<h4>{{l.FriendlyName}}</h4>
<div>
<div ng-repeat="limitinfo in l.LimitInfos">
<my-checkbox label="{{limitinfo.FriendlyName}}" value="{{limitinfo.Id}}" output="vm.settings.ComponentInfos"></my-checkbox>
</div>
</div>
</div>
<hr>
<pre>
{{vm.settings | json }}
</pre>
</body>
</html>
You can use the ng-click and make an update of your list.
I've added this to your MyViewModel function and changed the type of your ComponentInfosto an array.
this.update = function (value) {
var exists = false;
for (var elem of this.settings["ComponentInfos"]){
if (elem === value) {
exists = true;
}
}
if(exists) {
var index = this.settings["ComponentInfos"].indexOf(value);
this.settings["ComponentInfos"].splice(index,1);
} else {
this.settings["ComponentInfos"].push(value);
}
}
Additionally you need to change the input in the html to
<input type="checkbox" ng-click="vm.update(limitinfo.Id)"/> {{limitinfo.FriendlyName}}
I am new to angularJS, Try this :
Add this snippet to app.js
this.data =[];
this.selection = function(){
this.data =[];
angular.forEach(this.settings["ComponentInfos"], function(value, key) {
if(value)
this.push(key);
}, this.data);
}
This to body of index.html
<div ng-repeat="l in vm.components.ComponentInfos">
<h4>{{l.FriendlyName}}</h4>
<div>
<div ng-repeat="limitinfo in l.LimitInfos">
<label>
<input type="checkbox" ng-model="vm.settings.ComponentInfos[limitinfo.Id]" ng-click="vm.selection()"
value="{{limitinfo.Id}}"/> {{limitinfo.FriendlyName}}
</label>
</div>
</div>
</div>
<hr>
<pre>
{{vm.settings | json }}
{{vm.data}}
</pre>
Related
Here is my plunker : http://plnkr.co/edit/pnJ7q62eyBILTvX1f2dj?p=preview
In console.log() you can see, that after Update array is like :
{ age : "1", weight : "1"}
and i want like this :
{ age : 1, weight : 1}
Thanks for answers in advance!!!
You can use Object.entries and reduce's array method to do so:
const obj = Object.entries({ age : "1", weight : "1"})
.reduce((r, v) => (r[v[0]] = +v[1], r), {});
console.log(obj);
Use parseInt() to change the string values to integer. You could also use parseFloat() but the age and weight will not be a floating point values so parseInt() make more sense here.
var obj = {age : "1", weight : "1"};
for(var i in obj){
obj[i] = parseInt(obj[i]);
}
console.log(obj);
Based on your plunkr array:
var items = [
{
"params": {
"age": "22",
"weight": "66"
}
},
{
"params": {
"age": "19",
"weight": "54"
}
},
{
"params": {
"age": "17",
"weight": "75"
}
}
];
items.forEach((obj)=>{
var paramObj = obj.params;
for(var i in paramObj){
paramObj[i] = parseInt(paramObj[i]);
}
});
console.log(items);
You can loop through your array and convert string to number:
var arr = [{ age : "1", weight : "1"}, { age : "2", weight : "2"} ];
arr.forEach(e => {
e.age = +e.age;
e.weight = +e.weight;
});
console.log(arr);
You can create a modified object using Object.keys() and reduce():
let obj = { age : "1", weight : "1"};
let result = Object.keys(obj).reduce((a, c) => (a[c] = Number(obj[c]), a), {});
console.log(result);
Simply use parseInt()
Replace the following in your add function
$scope.params.age = parseInt(age);
$scope.params.weight = parseInt(weight);
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [
{
"params": {
"age": 22,
"weight": 66
}
},
{
"params": {
"age": 19,
"weight": 54
}
},
{
"params": {
"age": 17,
"weight": 75
}
}
]
$scope.add = function(params , age, weight) {
$scope.params = params;
if(age)
$scope.params.age = parseInt(age);
if(weight)
$scope.params.weight = parseInt(weight);
console.log($scope.params);
}
$scope.update = function(){
}
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="n in items">
<ul ng-repeat="(name, param) in n.params" style="list-style-type: none;">
<li>{{name}} : {{param}}</li>
</ul>
<input style="display:inline;width:130px;margin-bottom:5px;margin-top:5px;" class="form-control" name="text" placeholder="age" ng-model="age">
<input style="display:inline;width:115px;margin-bottom:5px;margin-top:5px;" class="form-control" name="text" placeholder="weight" ng-model="weight">
<br />
<button class="btn btn-warning" type="button" ng-click="add(n.params , age , weight)">Update</button>
</div>
<br />
</body>
</html>
Change the inputs to type="number":
<input placeholder="age" type="number" ng-model="age">
<input placeholder="weight" type="number" ng-model="weight">
<button class="btn btn-warning" type="button"
ng-click="add(n.params , age , weight)">
Update
</button>
OR convert to number in add function:
$scope.add = function(params , age, weight) {
$scope.params = params;
age && $scope.params.age = +age;
weight && $scope.params.weight = +weight;
};
I have one JSON array...
{
"Name" : "ABC",
"rating": [
{
"id": null,
"Percentage": 40
},
{
"id": 0,
"Percentage": 40
},
{
"id": 1,
"Percentage": 20
}
],
"email" : "abc#abc.com"
}
And i want to get only percentage with id 0 and 1 not null(skip)...
I am displaying this array in html with ng-repeat..., and i want to display only percentages with id is equal to 0 and 1 not null (skip).
This should be the ng-repeat for the array structure:
<div
ng-repeat="item in items"
ng-show="item.id != null && item.id == 0 || item.id == 1">
</div>
This is the array only, not the json object, you'll have to loop through that too prior to this.
If you only want to have those in the HTML, which 0 or 1 in the HTML, you can use the following code snippet:
HTML:
<div ng-repeat="rating in object.rating | filter: skipNull">
Angular Controller:
$scope.skipNull = function(item) {
return item.id === 0 || item.id === 1;
}
Here is a JSFiddle.
You are probably better off, if you are using a function like this, which only checks for null and undefined:
$scope.skipNull = function(item) {
return (typeof item.id !== "undefined" && item.id !== null);
}
You can use a custom filter. Like in this answer.
angular.module('app', []).
controller('ctrl', function($scope) {
$scope.data = {
"Name" : "ABC",
"rating": [
{
"id": null,
"Percentage": 40
},
{
"id": 0,
"Percentage": 40
},
{
"id": 1,
"Percentage": 20
}
],
"email" : "abc#abc.com"
};
$scope.noNull = function(item) {
return item.id != null;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="item in data.rating | filter:noNull" ng-bind="item.Percentage"></li>
</ul>
</div>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $http) {
$scope.results = [{
"Name": "ABC",
"rating": [{
"id": null,
"Percentage": 40
}, {
"id": 0,
"Percentage": 40
}, {
"id": 1,
"Percentage": 20
}],
"email": "abc#abc.com"
}] ;
$scope.resultstobeDisplayed = [];
angular.forEach($scope.results[0].rating, function(val) {
if (val.id != null) {
$scope.resultstobeDisplayed.push(val);
}
});
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/1.6.1/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="vale in resultstobeDisplayed">
<h1>{{vale}}</h1>
</div>
</body>
</html>
You can use ng-if
<div ng-repeat="rating in object.rating" ng-if="rating.id != null">
You can create your filter function into the controller like this:
Controller:
$scope.hideNullRatings = function(item) {
return item.id ===0 || item.id === 1;
}
HTML:
ng-repeat='item in items | filter: hideNullRatings'
You have to use ng-if directive. All you have to do is to apply it:
ng-if="item.id!=null"
function TodoCtrl($scope) {
$scope.data={ "Name" : "ABC", "rating": [ { "id": null, "Percentage": 40 }, { "id": 0, "Percentage": 40 }, { "id": 1, "Percentage": 20 } ], "email" : "abc#abc.com" };
}
td{
border:1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>
<div ng-app>
<div ng-controller="TodoCtrl">
<table>
<tr>
<th>Id</th>
<th>Percentage</th>
</tr>
<tr ng-repeat="item in data.rating" ng-if="item.id!=null">
<td>{{item.id}}</td>
<td>{{item.Percentage}}</td>
</tr>
</table>
</div>
</div>
I want to create a node tree from a json.
index.html should load node tree recursively from person.json
and now the method is going into infinite loop.
please help me.
app.js
(function() {
var app = angular.module("app", ['directive.cusTree', 'directive.cnode']);
app.controller("Contrl", function($scope, $http) {
$scope.some = function() {
return $http.get('person.json').success(function(data) {
$scope.nodetree = data;
return data;
});
}
});
})();
person.json
{
"person": [{
"id": 1,
"name": "A1" ,
"child": [{
"id": 1.1,
"name": "A11",
"child": [{
"id": 1.11,
"name": "A111"
}, {
"id": 1.12,
"name": "A112"
}, {
"id": 1.13,
"name": "A113"
}]
}, {
"id": 1.2,
"name": "A12"
}, {
"id": 1.3,
"name": "A13",
"child": [{
"id": 1.31,
"name": "A131"
}, {
"id": 1.32,
"name": "A132"
}, {
"id": 1.33,
"name": "A133"
}]
}]
}, {
"id": 2,
"name": "B2"
}, {
"id": 3,
"name": "C3"
}, {
"id": 4,
"name": "D4"
}
]
}
item.html
<div ng-click="show(show)" ng-init="show=true" class="container" ng-repeat="node in nodedata" ng-if="nodedata.length>0">
<ul>
{{node.name}}
<br>
<div ng-if="node.child.length>0">
<custree nodedata="node.child"> </custree>
</div>
</ul>
</div>
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="app.js" type="text/javascript"></script>
<script src="cusTree.js" type="text/javascript"></script>
<script src="cnode.js" type="text/javascript"></script>
</head>
<body>
<div ng-controller="Contrl as n">
<div ng-init="nodetree=some()">
<div ng-repeat="node in nodetree">
<div class="container">
<custree nodedata="node"> </custree>
</div>
<br>
</div>
</div>
</div>
</body>
</html>
cusTree.js
angular.module('directive.cusTree',[])
.directive('custree',function(){
return{
restrict :'E',
scope: {
nodedata:'='
},
templateUrl:"item.html",
controller:function($scope){
//console.log("new="+ JSON.stringify($scope.nodedata));
}
};
});
If you are creating tree with AngularJS, you have to create 2 directives as below:
app.directive('nodeTree', function () {
return {
template: '<node ng-repeat="node in tree"></node>',
replace: true,
restrict: 'E',
scope: {
tree: '=children'
}
};
});
app.directive('node', function ($compile) {
return {
restrict: 'E',
replace: true,
templateUrl: 'partials/node.html', // HTML for a single node.
link: function (scope, element) {
/*
* Here we are checking that if current node has children then compiling/rendering children.
* */
if (scope.node && scope.node.children && scope.node.children.length > 0) {
var childNode = $compile('<ul class="tree" ng-if="!node.visibility"><node-tree children="node.children"></node-tree></ul>')(scope);
element.append(childNode);
}
},
controller: ["$scope", function ($scope) {
// This function is for just toggle the visibility of children
$scope.toggleVisibility = function (node) {
node.visibility = !node.visibility;
};
// Here We are marking check/un-check all the nodes.
$scope.checkNode = function (node) {
node.checked = !node.checked;
function checkChildren(c) {
angular.forEach(c.children, function (c) {
c.checked = node.checked;
checkChildren(c);
});
}
checkChildren(node);
};
}]
};
});
For More details you can checkout Github Link, its have working demo.
HTML Code
<!doctype html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script>
document.write("<base href=\"" + document.location + "\" />");
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<h1> NG options</h1>
<form name="addUser">
Application:
<select ng-model="filterAddUser.application" ng-init ="filterAddUser.application = 'STACK'" title="" ng-options="value as value for (key , value) in applicationStatus">
</select>
Roles:
<select ng-model="filterAddUser.role" title="" ng-init ="filterAddUser.role = 'R'" ng-options="role.value as role.param for role in roleStatus">
</select>
<button ng-click="addToCart()">AddItem</button>
<div class="addCart">
<ul ng-repeat="item in items">
<li><b>Application:</b> {{item.application}}</li>
<li><b>Role:</b> {{item.role}}</li>
<li class="actionOptions">
<button ng-click="toggleSelected($index)">removeItem</button>
</li>
</ul>
</div>
</form>
</body>
</html>
Javascript Code
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [];
$scope.applicationStatus = {
"TEST App": "TEST",
"ABC App": "ABC",
"TRY App": "TRY",
"SIR App": "SIR",
"LOPR App": "LOPR",
"STACK App": "STACK"
};
$scope.roleStatus = [{
"param": "Read",
"value": "R"
}, {
"param": "Write",
"value": "W"
}, {
"param": "Admin",
"value": "A"
}, {
"param": "Super Approver",
"value": "SA"
}, {
"param": "Supervisor",
"value": "S"
}];
$scope.addToCart = function() {
$scope.items.push({
application: $scope.filterAddUser.application,
role: $scope.filterAddUser.role
});
// Clear input fields after push
$scope.filterAddUser['application'] = "";
$scope.filterAddUser['role'] = "";
}
$scope.toggleSelected = function(index) {
$scope.items.splice(index, 1);
};
});
All that i am trying to do is when i add the application to the cart that application needs to be removed from the dropdwon and also when i click on the remove item that needs to be pushed back to the cart i have included a plunker as well http://plnkr.co/edit/kSsetX?p=preview
need help on the same.
Updated your plunkr: http://plnkr.co/edit/QQobh7Jx76r7lDzw7TzV
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [];
var deletedApplication = [];
$scope.applicationStatus = {
"TEST App": "TEST",
"ABC App": "ABC",
"TRY App": "TRY",
"SIR App": "SIR",
"LOPR App": "LOPR",
"STACK App": "STACK"
};
$scope.roleStatus = [{
"param": "Read",
"value": "R"
}, {
"param": "Write",
"value": "W"
}, {
"param": "Admin",
"value": "A"
}, {
"param": "Super Approver",
"value": "SA"
}, {
"param": "Supervisor",
"value": "S"
}];
$scope.filterAddUser = {
application: $scope.applicationStatus[0],
role: $scope.roleStatus[0]
};
$scope.addToCart = function() {
deletedApplication.push([
$scope.filterAddUser.application, $scope.applicationStatus[$scope.filterAddUser.application]
]);
delete $scope.applicationStatus[$scope.filterAddUser.application];
$scope.items.push({
application: $scope.filterAddUser.application,
role: $scope.filterAddUser.role
});
// Clear input fields after push
$scope.filterAddUser['application'] = $scope.applicationStatus[0];
$scope.filterAddUser['role'] = $scope.roleStatus[0];
}
$scope.toggleSelected = function(index) {
var addApp = deletedApplication.filter(function(deletedApp){
return deletedApp[0] === $scope.items[index].application;
})[0];
$scope.applicationStatus[addApp[0]] = addApp[1];
console.log($scope.applicationStatus);
$scope.items.splice(index, 1);
};
});
I want to iterate over multiple array elements named urls and names. Below is the code where only urls are iterated. How can I use names also with urls?
JS
var app = angular.module('plunker',[]);
app.controller('Nav', function($scope) {
$scope.names = [
{
"name" : "myname 1",
},
{
"name": "myname 2"
}
]
$scope.urls = [
{
"url" : "http://google.com",
},
{
"url": "http://cnn.com"
}
];
});
HTML
<body ng-controller="Nav">
{{urls}}
{{names}}
<div ng-repeat="link in urls">
<input type="text" ng-model="link.url" />
<input type="text" /> //Want name here
</div>
</body>
Plnkr : http://plnkr.co/edit/OXXdFK2JElVaAh0uYmxG?p=preview
See answer in this plunker: http://plnkr.co/edit/OhnEpFjUVfLVUQw4TP3Z?p=preview
Add the ng-model like this:
<input type="text" ng-model="names[$index].name"/>
Every ng-repeat has some special properties exposed on local scope, see: http://docs.angularjs.org/api/ng.directive:ngRepeat
The one we are using is:
$index - iterator offset of the repeated element (0..length-1)
So as long as both arrays have the same length, this should work.
Can you change the code:
var app = angular.module('plunker',[]);
app.controller('Nav', function($scope) {
$scope.names = [
{
"name" : "myname 1",
},
{
"name": "myname 2"
}
]
$scope.urls = [
{
"url" : "http://google.com",
},
{
"url": "http://cnn.com"
}
];
});
to
var app = angular.module('plunker',[]);
app.controller('Nav', function($scope) {
$scope.urls = [
{
"name" : "myname 1",
"url" : "http://google.com"
},
{
"name": "myname 2",
"url": "http://cnn.com"
}
]
});
then in your HTML
<body ng-controller="Nav">
<div ng-repeat="url in urls">
<label>{{url.name}}<input type="text" ng-model="url.url" /></label>
</div>
</body>
http://plnkr.co/edit/6ne9jetDZTt4QhPctUpq?p=preview ?