Accessing an array within an array (ng-repeat) - arrays

I have a data structure like this:
[
{firstName: "John",
secondName: "Smith",
children: ["Fred", "Hannah"]
},
{firstName: "Daniel",
secondName: "Evans",
children: ["Maggie", "Eddie", "Maria"]
}
]
I want to use ng-repeat to return the CHILDREN of each person object, in a continuous list.
Like so:
<ul>
<li>Fred</li>
<li>Hannah</li>
<li>Maggie</li>
<li>Eddie</li>
<li>Maria</li>
</ul>
Can anyone help?

You could reduce your data structure before presenting it to the ng-repeat.
var app = angular.module('myApp', [
'my.controllers'
]);
var controllers = angular.module('my.controllers', []);
controllers.controller('MyController', function($scope) {
var people = [{
firstName: "John",
secondName: "Smith",
children: ["Fred", "Hannah"]
}, {
firstName: "Daniel",
secondName: "Evans",
children: ["Maggie", "Eddie", "Maria"]
}, {
firstName:"Childless",
secondName: "Parent"
},
{
firstName:"Jeff",
secondName: "Pasty",
children: ["Mike"]
}];
$scope.allChildren = people.reduce(function(a, b) { return a.concat(b.children) },[]);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyController">
<div ng-repeat='child in allChildren'>{{ child }}</div>
</div>
</div>

Related

VueJs v-for loop an array inside an array

I have a code as
<div v-for="benefit in service.benefits">
<p>{{benefit}}</p>
</div>
and here is the data
service: [
{title: 'blablabla',
price: '123',
benefits: ['a', 'b']},
{title: 'blaaablabla',
price: '12345',
benefits: ['aa', 'bb']},
]
I want to loop the data inside the benefits, but it doesn't work because v-for needs a key and in my case, there's no key for that. Is there any other way to loop this kind of data?
Thank you
you can use v-for inside v for :
var app = new Vue({
el: '#app',
data: {
service: [{
title: 'blablabla',
price: '123',
benefits: ['a', 'b']
},
{
title: 'blaaablabla',
price: '12345',
benefits: ['aa', 'bb']
},
]
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<div id="app">
<div v-for="(item, i) in service" :key="i">
<p>{{item.title}}</p>
<p>My Benefits :</p>
<p v-for="(benefit, index) in item.benefits" :key="index">
{{benefit}}
</p>
</div>
</div>
You could flatten benefits and make it a computed property, then iterating through it would be much easier
var app = new Vue({
el: '#app',
data: {
service: [{
title: 'blablabla',
price: '123',
benefits: ['a', 'b']
},
{
title: 'blaaablabla',
price: '12345',
benefits: ['aa', 'bb']
},
]
},
computed: {
benefits: function() {
return this.service.flatMap(({
benefits
}) => benefits)
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<div id="app">
<div v-for="(benefit, i) in benefits" :key="i">
<p>{{benefit}}</p>
</div>
</div>

AngularJS: How to bind properties of an object to scope

I am new to use AngularJS and I am an absolute beginner. I tried using filters. I tried binding to the properties instead of directly binding the object. But the code shows {{x.people}} as the output instead of showing the list. What am I missing out here?
<!DOCTYPE html>
<html>
<head>
<title>ANGULAR APP</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
</script>
</head>
<body ng-app="myApp" ng-controller="myFirstController">
<p>Type a letter in the input field:</p>
<p><input type="text" ng-model="test"></p>
<ul>
<li ng-repeat="x in model.people">
{{ x.name }}
</li>
</ul>
</body>
<script>
var app = angular.module('myApp', []);
var myFirstController = function($scope) {
$scope.model = {
people: [{
name: 'Jani',
country: 'Norway'
},
{
name: 'Carl',
country: 'Sweden'
},
{
name: 'Margareth',
country: 'England'
},
{
name: 'Hege',
country: 'Norway'
},
{
name: 'Joe',
country: 'Denmark'
},
{
name: 'Gustav',
country: 'Sweden'
},
{
name: 'Birgit',
country: 'Denmark'
},
{
name: 'Mary',
country: 'England'
},
{
name: 'Kai',
country: 'Norway'
}
];
};
}
app.controller('myFirstController', myFirstController);
</script>
</html>
there is an unnecessary ; at the end of your json data:
$scope.model = {
people:[
... // your data
{name:'Kai',country:'Norway'}]; // <------ here the ; is illegal
};
}
refer below fixed example:
var app = angular.module('myApp', []);
var myFirstController = function($scope) {
$scope.model = {
people: [{
name: 'Jani',
country: 'Norway'
},
{
name: 'Carl',
country: 'Sweden'
},
{
name: 'Margareth',
country: 'England'
},
{
name: 'Hege',
country: 'Norway'
},
{
name: 'Joe',
country: 'Denmark'
},
{
name: 'Gustav',
country: 'Sweden'
},
{
name: 'Birgit',
country: 'Denmark'
},
{
name: 'Mary',
country: 'England'
},
{
name: 'Kai',
country: 'Norway'
}
]
};
}
app.controller('myFirstController', myFirstController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myFirstController">
<p><input type="text" ng-model="test"></p>
<ul>
<li ng-repeat="x in model.people | filter: {name: test}">
{{ x.name }}
</li>
</ul>
</div>

How to bring dynamicaly scope in view

In my controller I have this code:
$scope.lists = [{
listName: 'list1'
}, {
listName: 'list2'
}];
angular.forEach($scope.lists, function(item) {
var listName = item.listName;
$scope[listName] = [{
Name: 'Stefan'
}, {
Name: 'Stefan'
}, {
Name: 'Stefan'
}, {
Name: 'Stefan'
}];
});
The Input from lists cames from a webservice, so the values (list1 and list2) can be different each time i reload the app. I can also more then 2 items in lists.
How can I show the value from $scope[listName] in an ng-repat section in my view?
Thanks for your Help.
Stefan.
You might try something like this:
(function() {
angular.module("myApp", []).controller("controller", ["$scope",
function($scope) {
$scope.lists = [{
listName: "list1"
}, {
listName: "list2"
}];
angular.forEach($scope.lists, function(item) {
var listName = item.listName;
$scope[listName] = [{
Name: "Stefan"
}, {
Name: "Stefan"
}, {
Name: "Stefan"
}, {
Name: "Stefan"
}];
$scope.results = $scope[listName];
});
}
]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="myApp">
<div data-ng-controller="controller">
<ul>
<li data-ng-repeat="item in results">{{item.Name}}</li>
</ul>
</div>
</div>

Kendo UI + Angular - v2014.2.903 vs v2014.3.1119 JSFiddle Issues

I am working on upgrading one of my Angular/Kendo UI projects from v2014.2.903 to v2014.3.1119. I have encountered a few instances where v2014.3.1119 breaks functionality that worked fine in v2014.2.903. I decided to create a couple JSFiddles to illustrate the issues, but unfortunately, the JSFiddle that points to v2014.2.903 doesn't seem to even recognize Kendo UI.
v2014.3.1119 JSFiddle (this works) ... http://jsfiddle.net/lejuan5150/w0711rdg/
v2014.2.903 JSFiddle (this doesn't work) ... http://jsfiddle.net/lejuan5150/4svqnaz6/
Both contain the same code and configuration aside from the version of Kendo UI they are referencing. Here is the code:
HTML:
<div>
<div data-ng-controller="personController">
<div
kendo-grid="personGrid"
k-options="personGridOptions"
k-ng-delay="personGridOptions">
</div>
<br />
First Name Combo Box:
<select
kendo-combo-box="firstNameComboBox"
k-options="firstNameComboBoxOptions"
k-ng-delay="firstNameComboBoxOptions"
k-ng-model="selectedPerson.firstName"
></select>
<br />
Last Name Combo Box:
<select
kendo-drop-down-list="lastNameDropDownList"
k-options="lastNameDropDownListOptions"
k-ng-delay="lastNameDropDownListOptions"
k-ng-model="selectedPerson.lastName"
></select>
</div>
JavaScript:
var app = angular
.module("app", [
"kendo.directives"
]);
app.controller("personController", [
"$scope",
personController
]);
function personController(
$scope
){
init();
function init(){
var personData = [{
firstName: "Joe",
lastName: "Smith",
status: "Active"
},{
firstName: "John",
lastName: "Smith",
status: "Active"
},{
firstName: "Travis",
lastName: "Smith",
status: "Expired"
}];
$scope.personDataSource = new kendo.data.DataSource({
data: personData
});
$scope.firstNamesData = [{
id: "Joe",
firstName: "Joe"
},{
id: "George",
firstName: "George"
},{
id: "John",
firstName: "John"
},{
id: "Travis",
firstName: "Travis"
}];
$scope.lastNamesData = [{
id: "Jones",
lastName: "Jones"
},{
id: "Smith",
lastName: "Smith"
}];
bindPersonGrid();
bindFirstNameComboBox();
bindLastNameDropDownList();
}
function bindPersonGrid(){
$scope.personGridOptions = {
dataSource: $scope.personDataSource,
selectable: "row",
dataBound: onPersonGridDataBound,
change: onPersonGridRowSelected
}
}
function onPersonGridDataBound(){
var grid = this;
var firstRow = grid.element.find("tbody tr:first");
grid.select(firstRow);
}
function onPersonGridRowSelected(
event
){
var grid = event.sender;
$scope.selectedPerson = grid.dataItem(grid.select());
$scope.$digest();
}
function bindFirstNameComboBox(){
$scope.firstNameComboBoxOptions = {
dataSource: $scope.firstNamesData,
dataTextField: "firstName",
dataValueField: "id"
};
}
function bindLastNameDropDownList(){
$scope.lastNameDropDownListOptions = {
dataSource: $scope.lastNamesData,
dataTextField: "lastName",
dataValueField: "id"
};
}
}
Does anyone know why the v2014.2.903 JSFiddle doesn't work?
I found the issue. Kendo v2014.2.903 doesn't like k-ng-delay when using a hard coded array of JavaScript objects.

Do I have to use $watch to dynamically pass isolate scope attributes to my custom controller?

I have a controller that stores super heroes. I would like to use a custom directive to display a certain super hero based on the value entered in an input field. I do not wish to achieve this with a filter. I am currently stuck, I am wondering if I need to implement something like $watch to do this? I would really like to do this with angular best practices. Thanks in advance!
heroController.js
var myApp = angular.module('myApp',[]);
myApp.controller('heroController', ['$scope', function($scope) {
$scope.superHero = [
{firstName: 'superman', image: 'img/url.com', superPower: 'invisibility'},
{firstName: 'batman', image: 'img/url.com', superPower: 'xray'},
{firstName: 'stretch', image: 'img/url.com', superPower: 'flight'},
{firstName: 'speedy', image: 'img/url.com', superPower: 'strength'},
{firstName: 'aquaman', image: 'img/url.com', superPower: 'aqua'},
{firstName: 'hulk', image: 'img/url.com', superPower: 'stretch'}
];
}]);
heroDirective.js
myApp.directive('heroDirective', function(){
return {
restrict: 'EA',
templateUrl: 'heroView.html',
replace: true,
scope: {
firstName: '#fname',
lastName: '#lname',
superPower: '#spower'
}
};
});
heroView.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<figure>
<ul>
<li>{{superHero.firstName}}</li>
<li>{{superHero.lastName}}</li>
<li>{{superHero.image}}</li>
<li>{{superHero.superPower}}</li>
</ul>
</figure>
</body>
</html>
index.html
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<body ng-app="myApp">
<div ng-controller="heroController">
<input ng-model="heroDirective.firstName"/>
<hero-directive ></hero-directive>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.js"></script>
<script src="heroController.js"></script>
<script src="heroDirective.js"></script>
</body>
Looks like a good case for a filter but since you requested not to use it, this is how i would implement it in angular:
http://plnkr.co/edit/rsStQ5lKdG9Qvm6X4Udz?p=preview
.html
<span>insert hero:</span>
<input ng-model="superHeroInput" />
<hero-directive super-hero="selectedSuperHero"></hero-directive>
.js
var app = angular.module('app', []);
app.controller('heroController', function($scope, $location, $timeout) {
$scope.superHeros = [{
firstName: 'superman',
image: 'img/url.com',
superPower: 'invisibility'
}, {
firstName: 'batman',
image: 'img/url.com',
superPower: 'xray'
}, {
firstName: 'stretch',
image: 'img/url.com',
superPower: 'flight'
}, {
firstName: 'speedy',
image: 'img/url.com',
superPower: 'strength'
}, {
firstName: 'aquaman',
image: 'img/url.com',
superPower: 'aqua'
}, {
firstName: 'hulk',
image: 'img/url.com',
superPower: 'stretch'
}];
$scope.superHeroInput = '';
$scope.$watch('superHeroInput', function(newValue) {
if (!newValue || newValue.length == 0) {
$scope.selectedSuperHero = $scope.superHeros[0];
} else {
var randomItem = $scope.superHeros[Math.floor(Math.random() * $scope.superHeros.length)];
$scope.selectedSuperHero = randomItem;
}
});
});
app.directive('heroDirective', function() {
return {
restrict: 'EA',
templateUrl: 'heroView.html',
replace: true,
scope: {
superHero: '='
}
};
});
heroView.html
<figure>
<ul>
<li>{{superHero.firstName}}</li>
<li>{{superHero.image}}</li>
<li>{{superHero.superPower}}</li>
</ul>
</figure>
so what's happening?
the input text bounded to superHeroInput. when it changes, $scope.$watch('superHeroInput', ... is invoked with the new input and then if there is empty string i picked the first superhero, otherwise, random superhero (you should place your superhero filtering logic there)
after that there is a binding between the selected superhero and the directive. when the selected superhero is changed, the directive updates his view

Resources