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 ?
Related
I'm trying to filter my ng-repeat through a set of checkboxes which come from a different object. Object 1 holds my categories and object 2 holds all my articles.
The categores object will turn into checkboxes. These checkboxes should act as filter for the articles. An article can have mutliple categories.
$scope.categories:
[
{
"id": "1",
"title": "Blog"
},
{
"id": "2",
"title": "News"
}
]
$scope.articles:
[
{
"id": "1",
"title": "Whats going on",
"categories":{
"results" : [1,2,3]
}
},
{
"id": "2",
"title": "Trump!",
"categories":{
"results" : [3]
}
}
]
Checkboxes:
<div class="filter-pills" ng-repeat="cat in categories">
<input type="checkbox" ng-model="filter[cat.Id]" ng-checked="cat.checked"/>{{cat.Title}}
</div>
ng-repeat:
<div class="col-lg-3 col-md-4" ng-repeat="item in articlesFinal"></div>
I have tried different solutions like ng-change when i update my filter array and compare it to the object used in ng-repeat.
I can't seem to figure this one out. Any suggestions?
Try this
<div class="filter-pills" ng-repeat="cat in categories">
<input type="checkbox" ng-model="cat.checked"/>{{cat.title}}
</div>
<div class="col-lg-3 col-md-4" ng-repeat="item in articles | filter: catFilter">{{item.title}}</div>
and in controller
$scope.catFilter = function (article) {
var checkedCats = vm.categories.filter(function (cat) {
return cat.checked;
});
// no filter, show all
if(checkedCats.length == 0) return true;
for(var i = 0; i < checkedCats.length; i++){
var id = checkedCats[i].id;
if(article.categories.results.indexOf(id) >= 0){
return true;
}
}
// no match, then false
return false
};
Also notice that category id should be integer, not string
$scope.categories = [
{
"id": 1, // integer
"title": "Blog"
},
{
"id": 2,
"title": "News"
}
];
$scope.articles = [
{
"id": "1",
"title": "Whats going on",
"categories":{
"results" : [1,2,3] // integer
}
},
{
"id": "2",
"title": "Trump!",
"categories":{
"results" : [3]
}
}
];
Below is the fiddle i am working:
http://jsfiddle.net/3c0dxf4d/
The ng-model has an object and the ng-value maps to object, why is my default value {"id":1,"name":"Bill"}
not getting selected by default.
Check out this fiddle http://jsfiddle.net/roz98eda/
var app = angular.module("app", []);
app.controller("ctrl", function($scope) {
$scope.customers = [{
"id": 1,
"name": "Bill"
}, {
"id": 2,
"name": "Bob"
}, {
"id": 3,
"name": "Biff"
}];
$scope.customer = {};
$scope.currentCustomer = {
"id": 1
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ctrl">
<table>
<tr ng-repeat="theCustomer in customers">
<td>
<input type="radio" ng-model="$parent.currentCustomer.id" ng-value="theCustomer.id">{{theCustomer.name}}</td>
</tr>
</table>
<br>
<div>{{currentCustomer}}</div>
</div>
</div>
Because you've put the initial value to
$scope.currentCustomer = {
"id": 1,
"name": "Bill"
};
Just remove or change it.
Please check following code please.
app.controller("ctrl", function ($scope) {
$scope.customers = [{
"id": 1,
"name": "Bill"
}, {
"id": 2,
"name": "Bob"
}, {
"id": 3,
"name": "Biff"
}];
$scope.customer = {};
*$scope.currentCustomer = {
"id": 1,
"name": "Bill"
};*
})
Change
<input type="radio" ng-model="$parent.currentCustomer" name="foo" ng-value="theCustomer" id="{{theCustomer.id}}">
To
<input type="radio" ng-model="$parent.currentCustomer.id" name="foo" ng-value="theCustomer.id" id="{{theCustomer.id}}">{{theCustomer.name}}</td>
From ng-value docs
It is mainly used on input[radio] and option elements, so that when
the element is selected, the ngModel of that element (or its select
parent element) is set to the bound value.
I am trying to sort a nested list of json objects on one of the properties of which is a "date" field. The date field is in MM/dd/yyyy format.
This is the HTML code:
<body ng-app="Test" ng-controller="TestController as testCtrl" ng-init="testCtrl.displayList()">
<ul ng-repeat="de in testCtrl.listToBeDisplayed">
<li >{{ de.empId }} {{ de.empName }} {{ de.joinDate }}</li>
</ul>
<button type="button" ng-click="testCtrl.sortList()">Test Button</button>
// This is the script:
<script>
angular.module("Test",[]);
angular.module("Test").controller("TestController",TestController);
TestController.$inject = ['orderByFilter','$filter'];
function TestController(orderBy,$filter){
vm = this;
vm.demoList = [
{
"Employees" :
[{
"id" : "1001",
"name": "Andre",
"date": "05/20/2016"
},
{
"id" : "1002",
"name": "Chris",
"date": "04/11/2016"
},
{
"id" : "1003",
"name": "Darren",
"date": "03/11/2016"
},
{
"id" : "1004",
"name": "Marlen",
"date": "08/11/2016"
}]
}
];
propertyName = 'date';
vm.displayList = function(){
console.log("in display List fn");
empList=[];
for(var i=0;i<vm.demoList[0].Employees.length;i++)
{
value = vm.demoList[0].Employees[i];
console.log("value="+value);
var employee = {
empId: '',
empName: '',
joinDate: ''
};
employee.empId = value.id;
employee.empName = value.name;
employee.joinDate = $filter('date')(new Date(value.date), "MM/dd/yyyy");
empList[i] = employee;
}
vm.listToBeDisplayed = empList;
}
</script>
</body>
When I click the button, the list is not getting sorted properly.
I have referred Angular documentation for orderBy filter: https://docs.angularjs.org/api/ng/filter/orderBy
This is the plunker I created for the above situation:
https://plnkr.co/edit/Q1m24arssRxC6B3NNO0n?p=preview
Any help on this ?
Call the correct function in your html:
<button type="button" ng-click="testCtrl.sortList()">Test Button</button>
And order on correct property name:
vm.sortList = function () {
vm.listToBeDisplayed = orderBy(empList, 'joinDate', true);
}
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>
I've tried for some time now to figure out how to data-bind a child in an object in Knockout js. I hope someone can help me solve this :)
I want to display the obj.externalLinks.facebook. I can't figure out how to data-bind it. This is what I have:
Model:
var obj = ko.observable();
var data = { "id" : 1,
"itemName" : "item name",
"price": 250,
"ticketLink" : "http://google.com",
"externalLinks" : [
{ "homePage" : "http://google.com" },
{ "mySpace" : "http://myspace.com" },
{ "facebook" : "http://facebook.com" },
{ "wikipedia" : "http://en.wikipedia.org/" },
{ "facebookEventPage" : "http://facebook.com" }
]
}
obj(data);
ko.applyBindings(obj)
View:
<h1 data-bind="text: externalLinks[2]"></h1>
I know the data-bind part is wrong, but how do I do it? :(
Try this one
Html
<span data-bind="text: link('facebook')"></span>
JavaScript
var data = { "id" : 1,
"itemName" : "item name",
"price": 250,
"ticketLink" : "http://google.com",
"externalLinks" : [
{ "homePage" : "http://google.com" },
{ "mySpace" : "http://myspace.com" },
{ "facebook" : "http://facebook.com" },
{ "wikipedia" : "http://en.wikipedia.org/" },
{ "facebookEventPage" : "http://facebook.com" }]
};
var ViewModel = function(rawData){
var self = this;
var data = rawData;
self.link = function(linkKey){
for (var i=0; i<data.externalLinks.length; i++){
var item = data.externalLinks[i];
if(item[linkKey]){
return item[linkKey];
}
}
};
};
ko.applyBindings(new ViewModel(data));
So you can bind to the link by linkKey
jsfiddle sample