AngularJS ng-repeat with nested json - angularjs

my json look like below
$scope.peoples = [people:{
name: 'Mike ',
age: 20
}, people:{
name: 'Peter S ',
age: 22
}];
Notes: i can not change json structure.
here is my code where ng-repeat could not read json.
<div ng-controller="MyCtrl">
<table class="table table-hover">
<tr ng-repeat="p in peoples">
<td> Name: {{ p.name }} </td>
<td> Age: {{ p.age }} </td>
</tr>
</table>
</div>
var app = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.peoples = [people:{
name: 'Mike ',
age: 20
}, people:{
name: 'Peter S ',
age: 22
}];
}

Looks like your json array is defined in wrong way:
$scope.peoples = [{
name: 'Mike ',
age: 20
},{
name: 'Peter S ',
age: 22
}];
notice there is no people object. you defined people without an object. If you fix your json your code will work fine.
Here's the working code with json fix : http://jsfiddle.net/Lvc0u55v/2236/
Other way of fixing the existing code with the people object is, you move the people in javascript object as shown below:
Javascript:
$scope.peoples = [{
people : {
name: 'Mike ',
age: 20
}},{
people: {
name: 'Peter S ',
age: 22
}}];
Html:
<td> Name: {{ p.people.name }} </td>
<td> Age: {{ p.people.age }} </td>
This way your can use the people object. Here's the working code : http://jsfiddle.net/Lvc0u55v/2237/
Overall, i would recommend using first approach instead of second one.

Related

FileSaver.js saveAs(Xlsx)

I am using filesaver.js to export my div (with multiple tables) to excel. I am able to export it as XLS using the code below.
var blob = new Blob([document.getElementById('exportable').innerHTML], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
});
saveAs(blob, "Test Report using FileSaver.xls");
However, I want to export my div to XLSX. Can anyone help? I have tried changing the MIME type to XLSX, but didn't help.
Update
W3C does not implemented .xlsx so the browsers too. But you can use alsql a js library which export data as a valid .xlsx here is the jsfiddle or run below code
function myCtrl($scope) {
$scope.exportData = function () {
alasql('SELECT * INTO XLSX("Report.xlsx",{headers:true}) FROM ?',[$scope.items]);
};
$scope.items = [{
name: "John Smith",
email: "j.smith#example.com",
dob: "1985-10-10"
}, {
name: "Jane Smith",
email: "jane.smith#example.com",
dob: "1988-12-22"
}, {
name: "Jan Smith",
email: "jan.smith#example.com",
dob: "2010-01-02"
}, {
name: "Jake Smith",
email: "jake.smith#exmaple.com",
dob: "2009-03-21"
}, {
name: "Josh Smith",
email: "josh#example.com",
dob: "2011-12-12"
}, {
name: "Jessie Smith",
email: "jess#example.com",
dob: "2004-10-12"
}];
};
<script src="https://cdn.jsdelivr.net/alasql/0.3.6/alasql.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.7.2/xlsx.core.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="myCtrl">
<button ng-click="exportData()">Export</button>
<br />
<div id="exportable">
<table width="100%">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>DoB</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>{{item.name}}</td>
<td>{{item.email}}</td>
<td>{{item.dob | date:'MM/dd/yy'}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

How to make function that will save changes in select form and apply them on table using AngularJs

I'm trying to make function that will save changes made in select form and apply them to my table.
In table I'm displaying name, designation and company of employees. I want to use select form to select the name of company. When I select company name and then click save button as result I only want to display names, designations and company of employees that work for that selected company. Also I want to display number of rows left in table after filtering the table.
Code I have so far is here:
data.html
<div ng-app="MyApp" ng-controller="MyController">
<div>
<table>
<tr>
<th style="width:10%">#</th>
<th style="width:20%">Name</th>
<th style="width:40%">Designation</th>
<th style="width:30%">Company</th>
</tr>
<tr ng-repeat="employee in clients | filter:searchText">
<td>{{$index + 1}}</td>
<td>{{employee.name}}</td>
<td>{{employee.designation}}</td>
<td>{{employee.company.name}}</td>
</tr>
</table>
</div>
<div>
<h2>Select Company:</h2>
<select ng-model="searchText.company.name">
<option ng-repeat="c in clients" value="{{c.company.name}} ">{{c.company.name}}</option>
</select>
<h3>You selected: {{searchText.company.name}</h3>
<button ng-click="updateSearch()">Save</button>
<b>input: {{searchText.company.name}}</b>
</div>
</div>
data.js
var controllers = angular.module('MyApp', [])
controllers.controller('MyController', function ($scope) {
$scope.clients = [{
name: 'Brett',
designation: 'Software Engineer',
company: {
name: 'Apple'
}
}, {
name: 'Steven',
designation: 'Database Administrator',
company: {
name: 'Google'
}
}, {
name: 'Jim',
designation: 'Designer',
company: {
name: 'Facebook'
}
}, {
name: 'Michael',
designation: 'Front-End Developer',
company: {
name: 'Apple'
}
}, {
name: 'Josh',
designation: 'Network Engineer',
company: {
name: 'Google'
}
}, {
name: 'Ellie',
designation: 'Internet Marketing Engineer',
company: {
name: 'Apple'
}
}];
$scope.updateSearch = function() {
console.log($scope.searchText.company.name);
}
});
Now I'm selecting company name immediately after choosing it from select form, but I want it to be applied after clicking on save button.
If anybody can help, thanks!
Hope this below code snippet helps you ! Its pretty much self explanatory.
UPDATE
To display count use below syntax in ng-repeat
<tr ng-repeat="employee in filteredList = (clients | filter:searchText)">
var controllers = angular.module('MyApp', [])
controllers.controller('MyController', function($scope) {
$scope.selected ={};
$scope.searchText ={}
$scope.searchText.company={};
$scope.filteredList =[];
$scope.clients = [{
name: 'Brett',
designation: 'Software Engineer',
company: {
name: 'Apple'
}
}, {
name: 'Steven',
designation: 'Database Administrator',
company: {
name: 'Google'
}
}, {
name: 'Jim',
designation: 'Designer',
company: {
name: 'Facebook'
}
}, {
name: 'Michael',
designation: 'Front-End Developer',
company: {
name: 'Apple'
}
}, {
name: 'Josh',
designation: 'Network Engineer',
company: {
name: 'Google'
}
}, {
name: 'Ellie',
designation: 'Internet Marketing Engineer',
company: {
name: 'Apple'
}
}];
$scope.orginalList = angular.copy($scope.clients);
$scope.updateSearch = function() {
$scope.searchText.company.name = $scope.selected.company;
}
});
<script data-require="angularjs#1.5.8" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="MyController">
<div>
<table>
<tr>
<th style="width:10%">#</th>
<th style="width:20%">Name</th>
<th style="width:40%">Designation</th>
<th style="width:30%">Company</th>
</tr>
<tr ng-repeat="employee in filteredList = (clients | filter:searchText)">
<td>{{$index + 1}}</td>
<td>{{employee.name}}</td>
<td>{{employee.designation}}</td>
<td>{{employee.company.name}}</td>
</tr>
</table>
Count : {{filteredList.length}}/{{orginalList.length}}
</div>
<div>
<h2>Select Company:</h2>
<select ng-model="selected.company">
<option ng-repeat="c in clients" value="{{c.company.name}} ">{{c.company.name}}</option>
</select>
<h3>You selected: {{selected.company}}</h3>
<button ng-click="updateSearch()">Save</button>
<b>input: {{searchText.company.name}}</b>
</div>
</div>
Is that you want?
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</head>
<body>
<div ng-app="MyApp" ng-controller="MyController">
<div>
<table>
<tr>
<th style="width:10%">#</th>
<th style="width:20%">Name</th>
<th style="width:40%">Designation</th>
<th style="width:30%">Company</th>
</tr>
<tr ng-repeat="employee in clients | filter:searchText">
<td>{{$index + 1}}</td>
<td>{{employee.name}}</td>
<td>{{employee.designation}}</td>
<td>{{employee.company.name}}</td>
</tr>
</table>
</div>
<div>
<h2>Select Company:</h2>
<select ng-model="searchText1.company.name">
<option ng-repeat="c in clients" value="{{c.company.name}} ">{{c.company.name}}</option>
</select>
<h3>You selected: {{searchText.company.name}</h3>
<button ng-click="updateSearch()">Save</button>
<b>input: {{searchText.company.name}}</b>
</div>
</div>
<script>
var controllers = angular.module('MyApp', [])
controllers.controller('MyController', function($scope) {
$scope.clients = [{
name: 'Brett',
designation: 'Software Engineer',
company: {
name: 'Apple'
}
}, {
name: 'Steven',
designation: 'Database Administrator',
company: {
name: 'Google'
}
}, {
name: 'Jim',
designation: 'Designer',
company: {
name: 'Facebook'
}
}, {
name: 'Michael',
designation: 'Front-End Developer',
company: {
name: 'Apple'
}
}, {
name: 'Josh',
designation: 'Network Engineer',
company: {
name: 'Google'
}
}, {
name: 'Ellie',
designation: 'Internet Marketing Engineer',
company: {
name: 'Apple'
}
}];
$scope.updateSearch = function() {
$scope.searchText = $scope.searchText1.company.name;
console.log($scope.searchText.company.name);
}
});
</script>
</body>
</html>

Angulajs: How to apply filter using select form after clicking save button?

In table I'm displaying name, designation and company of employees. I want to use select form to select the name of company. When I select company name and then click save button as result I only want to display names, designations and company of employees that for example work for Google.
Also I want to have displayed number of how many employee is it.
But kinnda got stucked my save button is not working, and also don't have number of employe.
file.html
<body ng-controller="MyController">
<div>
<table>
<tr>
<th style="width:10%">#</th>
<th style="width:20%">Name</th>
<th style="width:40%">Designation</th>
<th style="width:30%">Company</th>
</tr>
<tr ng-repeat="employee in clients">
<td>{{$index + 1}}</td>
<td>{{employee.name}}</td>
<td>{{employee.designation}}</td>
<td>{{employee.company.name}}</td>
</tr>
</table>
</div>
<div>
<ul>
<li>
<h2>Select Company:</h2>
<select ng-model="selectedCompany">
<option ng-repeat="c in companyList" value="{{c.name}}">{{c.name}}</option>
</select>
<h3>You selected: {{selectedCompany}}</h3>
</li>
</ul>
<button ng-click="$ctrl.updateSearch()">Filter</button>
</div>
</body>
file.js
var controllers = angular.module('MyApp.controllers', [])
controllers.controller('MyController', function ($scope) {
$scope.clients = [{
name: 'Brett',
designation: 'Software Engineer',
company: {
name: 'Apple'
}
}, {
name: 'Steven',
designation: 'Database Administrator',
company: {
name: 'Google'
}
}, {
name: 'Jim',
designation: 'Designer',
company: {
name: 'Facebook'
}
}, {
name: 'Michael',
designation: 'Front-End Developer',
company: {
name: 'Apple'
}
}, {
name: 'Josh',
designation: 'Network Engineer',
company: {
name: 'Google'
}
}, {
name: 'Ellie',
designation: 'Internet Marketing Engineer',
company: {
name: 'Apple'
}
}];
$scope.companyList = [{
name: 'Apple',
slug: 'Apple'
}, {
name: 'Google',
slug: 'Google'
}, {
name: 'Microsoft',
slug: 'Microsoft'
}, {
name: 'Facebook',
slug: 'Facebook'
},
];
$scope.updateSearch = function() {
console.log($scope.selectedCompany);
}
});
There are few changes needs to be done on your view, Change your model variables to be different from the array names, such as colorn,sizen and brandn.
<div>
<label>Color:</label>
<select ng-model="colorn" ng-options="option.name for option in colorStatus track by option.slug"></select>
</div>
<div>
<label>Size</label>
<select ng-model="sizen" ng-options="option.name for option in size track by option.slug"></select>
</div>
<div>
<label>Brand</label>
<select ng-model="brandn" ng-options="option.name for option in $ctrl.brand track by option.slug"></select>
</div>
<button ng-click="updateSearch()">Save</button>
Also you can get the values using your $scope variable,
Controller
$scope.updateSearch = function(){
console.log($scope.colorn);
console.log($scope.sizen);
console.log($scope.sizen);
}
DEMO

Iterate on ng-repeat

Im trying to figure out how the variables are called in angular. Im new to angularjs and cant seem to figure out why in the first example we are iterating in the ng-repeat 'group in $groups' and in the second example we are iterating over 'user in $data', i cant seem to figure out where $groups and $data come from and why i cant change the name on both examples and keep it working, so i can now how to call them in my own example.
First example: http://plnkr.co/edit/CBcbkc?p=preview
var app = angular.module('main', ['ngTable']).
controller('DemoCtrl', function($scope, $filter, ngTableParams) {
var data = [{name: "Moroni", age: 50, role: 'Administrator'},
{name: "Tiancum", age: 43, role: 'Administrator'},
{name: "Jacob", age: 27, role: 'Administrator'},
{name: "Nephi", age: 29, role: 'User'},
{name: "Enos", age: 34, role: 'User'}];
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
groupBy: 'role',
total: data.length,
getData: function($defer, params) {
var orderedData = params.sorting() ?
$filter('orderBy')(data, $scope.tableParams.orderBy()) :
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
})
<table ng-table="tableParams" class="table">
<tbody ng-repeat="group in $groups">
<tr class="ng-table-group">
<td colspan="{{$columns.length}}">
<a href="" ng-click="group.$hideRows = !group.$hideRows">
<span class="glyphicon" ng-class="{ 'glyphicon-chevron-right': group.$hideRows, 'glyphicon-chevron-down': !group.$hideRows }"></span>
<strong>{{ group.value }}</strong>
</a>
</td>
</tr>
<tr ng-hide="group.$hideRows" ng-repeat="user in group.data">
<td sortable="name" data-title="'Name'">
{{user.name}}
</td>
<td sortable="age" data-title="'Age'">
{{user.age}}
</td>
</tr>
</tbody>
</table>
Second example: http://plnkr.co/edit/HUe0e1zBGOG9oOyqpGq9?p=preview
var app = angular.module('main', ['ngTable']).
controller('DemoCtrl', function($scope, $filter, ngTableParams) {
$scope.myValues = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.tableParams = new ngTableParams({
sorting: {
name: 'asc'
}
}, {
getData: function($defer, params) {
$defer.resolve($filter('orderBy')($scope.myValues, params.orderBy()));
}
});
});
<button ng-click="tableParams.sorting({})" class="btn btn-default pull-right">Clear sorting</button>
<p><strong>Sorting:</strong> {{tableParams.sorting()|json}}
<table ng-table="tableParams" class="table">
<tr ng-repeat="user in $data">
<td data-title="'Name'" sortable="'name'">
{{user.name}}
</td>
<td data-title="'Age'" sortable="'age'">
{{user.age}}
</td>
</tr>
</table>
If you are trying to figure out how variables and angular works in general, THIS is a great tutorial.
If you're trying to figure out why you can't change the names in your examples, the answer is that you are using a custom directive called ng-table created by this guy to make life a little easier when dealing with tables in angular. Like if you wanted to "group" for example. So $data and $groups, are part of that.
In your example, you created a variable with a collection of objects in it called "myValues". That variable lives on the scope. You can access that data in the html, and use the ng-repeat from angular like so:
<table class="table">
<tr ng-repeat="user in myValues">
<td data-title="'Name'" sortable="'name'">
{{user.name}}
</td>
<td data-title="'Age'" sortable="'age'">
{{user.age}}
</td>
</tr>
</table>
Notice how you would no longer be using the directive "ng-table." user is defined in the html with your ng-repeat, you could just as easily call it "righteousDude in myValues" or "guy in myValues".
<table class="table">
<tr ng-repeat="righteousDude in myValues">
<td data-title="'Name'" sortable="'name'">
{{righteousDude.name}}
</td>
If you wanted the data name changed, you could change it where you define it in the .js file.
$scope.righteousDudes = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},.....ect
Just remember that ng-repeat is an angular directive that "instantiates a template once per item from a collection"
And your variable that you create in the ng-repeat...i.e. "user" represents that item. Hope that helps!

AngularJs grouping by property

I need a way to order a list by its properties.
I have this plunker: http://jsfiddle.net/Tropicalista/aF2aL/1/
but don't know hoe to proceed. I need a way to order the list based on what I select in checkboxes...
function myCtrl($scope){
$scope.friends = [
{
name: "Michael",
gender: "Male",
hair: "Brunette"
},
{
name: "George Michael",
gender: "Male",
hair: "Brunette"
},
{
name: "Gob",
gender: "Male",
hair: "Brunette"
},
{
name: "Tobias",
gender: "Male",
hair: "Black"
},
{
name: "Lindsay",
gender: "Female",
hair: "Blonde"
},
{
name: "Maeby",
gender: "Female",
hair: "Black"
}
];
$scope.orderBy = function(target){
$scope.groups = _.groupBy($scope.friends, target);
}
$scope.activeGroups = {};
}
And this is my html:
<input type="checkbox" ng-click="orderBy('name')" />Name
<input type="checkbox" ng-click="orderBy('gender')" />Gender
<input type="checkbox" ng-click="orderBy('hair')" />Hair
<div data-ng-repeat="(myFilter, users) in groups">
<h2>{{myFilter}}</h2>
<ul>
<li data-ng-repeat="user in users">
{{ user.name }}
</li>
</ul>
</div>
First, for something like this, I much prefer using a radio instead of a checkbox. It is semantically correct. Check boxes indicate that you can group by more than one field, and it doesn't appear, from your question, that you are trying to do that.
Knowing that, you can define your radios like this:
<input type="radio" ng-model="grouping" value="name" />Name
<input type="radio" ng-model="grouping" value="gender" />Gender
<input type="radio" ng-model="grouping" value="hair" />Hair
Now, you can just tell your ng-repeat to group based on a groupedFriends collection:
<div data-ng-repeat="(group, users) in groupedFriends">
<h2>{{group}}</h2>
<ul>
<li data-ng-repeat="user in users">
{{ user.name }}
</li>
</ul>
</div>
And then your controller just watches the grouping variable and group the data:
$scope.$watch('grouping', function() {
$scope.groupedFriends = _.groupBy($scope.friends, $scope.grouping);
});
$scope.grouping = "gender";
Here is a working fiddle.
STEVE HOLT!
You can use groupBy of angular.filter module, It's easy to use, and actually more fast than lodash implementation see: link.
Usage: (key, val) in collection | groupBy: 'property' or nested.property
here's an example:
JS:
$scope.players = [
{name: 'Gene', team: 'alpha'},
{name: 'George', team: 'beta'},
{name: 'Steve', team: 'gamma'},
{name: 'Paula', team: 'beta'},
{name: 'Scruath', team: 'gamma'}
];
HTML:
<ul ng-repeat="(key, value) in players | groupBy: 'team'">
Group name: {{ key }}
<li ng-repeat="player in value">
player: {{ player.name }}
</li>
</ul>
RESULT:
Group name: alpha
* player: Gene
Group name: beta
* player: George
* player: Paula
Group name: gamma
* player: Steve
* player: Scruath
UPDATE: jsbin

Resources