Problems facing while working on Isolated Scope concept of Angular - angularjs

I am trying to extend the example/answer (given by #sylwester) of the question I asked. Now I have to do something like this
What I have done so far?
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var arr1 = [
{"EmpId":1,"EmpName":"Michale Sharma","gender":"Male","age":25,"salary":10000},
{"EmpId":2,"EmpName":"Sunil Das","gender":"Male","age":24,"salary":5000},
{"EmpId":3,"EmpName":"Robin Pandey","gender":"Male","age":35,"salary":45000},
{"EmpId":4,"EmpName":"Mona Singh","gender":"Female","age":27,"salary":12000}
];
var arr2 = [
{"Deptid":4,"Deptname":"IT"},
{"Deptid":1,"Deptname":"HR"},
{"Deptid":3,"Deptname":"HW"},
{"Deptid":2,"Deptname":"HW4"}
];
var res = merge(arr1, arr2, "EmpId", "Deptid");
$scope.Employee = {
EmployeeName:res.EmpName,
EmployeeSex:res.gender
};
$scope.Department = {
DepartmentName:res.Deptname
};
//console.log(res);
}).
directive('myCustomer', function() {
return {
restrict: 'E',
scope: {
customer: '='
},
templateUrl: 'my-customer-plus-vojta.html'
};
});
function merge(arr1, arr2, prop1, prop2)
{
//alert("in merge");
return arr1.map(function(item){
var p = item[prop1];
var el = arr2.filter(function(item) {
return item[prop2] === p;
});
if (el.length === 0) {
return null;
}
var res = {};
for (var i in item) {
if (i !== prop1) {
res[i] = item[i];
}
}
for (var i1 in el[0]) {
if (i1 !== prop2) {
res[i1] = el[0][i1];
}
}
return res;
}).filter(function(el){return el !== null;});
}
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link href="style.css" rel="stylesheet" />
<script data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js" data-require="angular.js#1.3.x"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<table border="1">
<tr>
<td>EmployeeNames</td>
<td>Gender</td>
<td>Works For</td>
</tr>
<tr>
<my-customer customer="Employee"></my-customer>
<my-customer customer="Department "></my-customer>
</tr>
</table>
</body>
</html>
my-customer-plus-vojta.html (I am stuck here considering other things are correct. I equally know that li is not the correct way to use. However, I do not know what to do and how to do).
<h3>Employee-Department</h3>
<li ng-repeat="emp in customer.Employee">
<p ng-if="emp.EmployeeName">{{emp.EmployeeName}}</p>
<p ng-if="emp.EmployeeSex">{{emp.EmployeeSex}}</p>
</li>
<li ng-repeat="dept in customer.Department">
<p ng-if="dept.DepartmentName">{{dept.DepartmentName}}</p>
</li>

Please see demo below
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
var arr1 = [{
"EmpId": 1,
"EmpName": "Michale Sharma",
"gender": "Male",
"age": 25,
"salary": 10000
}, {
"EmpId": 2,
"EmpName": "Sunil Das",
"gender": "Male",
"age": 24,
"salary": 5000
}, {
"EmpId": 3,
"EmpName": "Robin Pandey",
"gender": "Male",
"age": 35,
"salary": 45000
}, {
"EmpId": 4,
"EmpName": "Mona Singh",
"gender": "Female",
"age": 27,
"salary": 12000
}
];
var arr2 = [{
"Deptid": 4,
"Deptname": "IT"
}, {
"Deptid": 1,
"Deptname": "HR"
}, {
"Deptid": 3,
"Deptname": "HW"
}, {
"Deptid": 2,
"Deptname": "HW4"
}];
$scope.res = merge(arr1, arr2, "EmpId", "Deptid");
});
app.directive('myCustomer', function() {
return {
restrict: 'AE',
scope: {
customer: '=myCustomer'
},
replace: true,
templateUrl: 'customerTmpl.html',
link: function(scope) {
console.log(scope)
}
};
});
function merge(arr1, arr2, prop1, prop2) {
//alert("in merge");
return arr1.map(function(item) {
var p = item[prop1];
var el = arr2.filter(function(item) {
return item[prop2] === p;
});
if (el.length === 0) {
return null;
}
var res = {};
for (var i in item) {
if (i !== prop1) {
res[i] = item[i];
}
}
for (var i1 in el[0]) {
if (i1 !== prop2) {
res[i1] = el[0][i1];
}
}
return res;
}).filter(function(el) {
return el !== null;
});
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app" ng-controller="MainCtrl">
<table class="table table-striped">
<tbody>
<tr ng-repeat="customer in res" my-customer="customer"></tr>
</tbody>
</table>
<script type="text/ng-template" id="customerTmpl.html">
<tr>
<td>{{customer.EmpName}}</td>
<td>{{customer.gender}}</td>
<td>{{customer.age}}</td>
<td>{{customer.salary}}</td>
<td>{{customer.Deptname}}</td>
</tr>
</script>
</body>

The problem is you can't just link to res.EmpName... Your res variable is an Array of Objects. You need to loop through that Array, then look inside that Object to grab what you need. Then, you can supply it as a part of your $scope key/value.
For example the 1st key of your res object:
Deptname: "HR"
EmpName: "Michale Sharma"
age: 25
gender: "Male"
salary: 10000
Create empty arrays for your new collections you need to make, then loop through the res object and add them to it.
var empNames = [],
empGenders = [],
empDepts = [];
for (key in res) {
empNames.push(res[key].EmpName);
empGenders.push(res[key].gender);
empDepts.push(res[key].Deptname);
}
// NOW you can apply them into your scope
$scope.Employee = {
EmployeeName : empNames,
EmployeeSex : empGenders
};
$scope.Department = {
DepartmentName : empDepts
};

Related

AngularJS Changing DropDowns according to DropDown Values for ng-repeat filters

I have a list of about 1400 locations around the world and displaying them using ng-repeat. I want to have dropdowns to narrow the list down using the filter feature so I can only see locations in Region: Americas, Country:Canda for example. I have gotten the dropdown filters to work properly but my issue is changing the values of the dropdowns. If I select the Region option in the first dropdown, the country dropdown should only have countries in that Region.
Here is my Template:
Region:<select ng-model='RegionLocation.Region' ng-options="location.Region for location in RegionOptions.Regions"></select>
Country:<select ng-model='CountryLocation.Country' ng-options="location.Country for location in CountryOptions.Countries"></select>
<div>
<md-card data-ng-repeat="location in LocationCtrl.Locationlist | filter:RegionFilter | filter:CountryFilter ">
<md-card-content>
<h2>{{::location.LID}}</h2>
</md-card-content>
</md-card>
</div>
Here is my Controller.js
function LocationController(LocationList, $scope) {
var LocationCtrl = this;
LocationCtrl.Locationlist = LocationList;
LocationCtrl.Regions = filterRegions(LocationList);
LocationCtrl.Regions.unshift({
Region: 'Show All'
})
$scope.RegionOptions = {
Regions:LocationCtrl.Regions,
}
$scope.RegionLocation = {
Region: $scope.RegionOptions.Regions[0],
}
$scope.CountryOptions = {
Countries:getCountries()
};
$scope.CountryLocation = {
Country: $scope.CountryOptions.Countries[0]
};
$scope.RegionFilter = function (data) {
if($scope.RegionLocation.Region.Region == 'Show All'){
return true;
} else if(data.Region == $scope.RegionLocation.Region.Region){
return true;
} else{
return false;
}
};
$scope.CountryFilter = function (data) {
if($scope.CountryLocation.Country.Country == 'Show All'){
return true;
} else if(data.Country == $scope.CountryLocation.Country.Country){
return true;
} else{
return false;
}
};
function getCountries(){
LocationCtrl.Countries = filterCountries(LocationList);
LocationCtrl.Countries.unshift({
Country: 'Show All'
});
return LocationCtrl.Countries;
};
function filterRegions(arr) {
var f = []
return arr.filter(function(n) {
return f.indexOf(n.Region) == -1 && f.push(n.Region)
})
};
function filterCountries(arr){
var f = [];
return arr.filter(function(n) {
return f.indexOf(n.Country) == -1 && f.push(n.Country)
})
};
}
I also understand my code is not super clean nor simple so suggestions to simplify it are more than welcome.
Thank you!!
You were on the right track with using a filter on the ng-repeat, here is how I managed to get it working based of some mock data. Its really simple to get this done using a filter. I hope this helps.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $filter) {
$scope.name = 'Sup World';
$scope.list = [{
"LID": "AB02",
"City": "Calgary",
"State": "Alberta",
"Country": "Canada",
"Region": "Americas",
"Latitude": "XXXXXX",
"Longitude": "XXXXX"
}, {
"LID": "AB08",
"City": "Canmore",
"State": "Alberta",
"Country": "Canada",
"Region": "Americas",
"Latitude": "XXXXXX",
"Longitude": "XXXXXXX"
}, {
"LID": "AB09",
"City": "Cape Town",
"State": "Western Cape",
"Country": "South Africa",
"Region": "Africa",
"Latitude": "XXXXXX",
"Longitude": "XXXXXXX"
}, {
"LID": "AB12",
"City": "Eish",
"State": "Somewhere",
"Country": "Zimbabwe",
"Region": "Africa",
"Latitude": "XXXXXX",
"Longitude": "XXXXX"
}, {
"LID": "AB18",
"City": "Lusaka",
"State": "Zambia?",
"Country": "Zambia",
"Region": "Africa",
"Latitude": "XXXXXX",
"Longitude": "XXXXXXX"
}, {
"LID": "AB19",
"City": "Durban",
"State": "Kwazulu Natal",
"Country": "South Africa",
"Region": "Africa",
"Latitude": "XXXXXX",
"Longitude": "XXXXXXX"
}, {
"LID": "AB13",
"City": "Pretoria",
"State": "JoJo",
"Country": "South Africa",
"Region": "Africa",
"Latitude": "XXXXXX",
"Longitude": "XXXXXXX"
}];
$scope.region = [];
//get unique regions
$scope.regions = $filter('unique')($scope.list, "Region");
$scope.country = [];
//get unique countries
$scope.countries = $filter('unique')($scope.list, "Country");
});
app.filter('unique', function() {
return function(arr, field) {
var o = {},
i, l = arr.length,
r = [];
for (i = 0; i < l; i += 1) {
o[arr[i][field]] = arr[i];
}
for (i in o) {
r.push(o[i]);
}
return r;
};
})
<!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.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
Region:
<select ng-model='region' ng-options="location.Region for location in regions"></select>
Country:
<select ng-model='country' ng-options="location.Country for location in countries | filter:{'Region': region.Region }"></select>
<div>
<md-card data-ng-repeat="location in list | filter:{'Region':region.Region,'Country':country.Country} ">
<md-card-content>
<h2>{{::location.LID}}</h2>
</md-card-content>
</md-card>
</div>
</body>
</html>
See this Plunker, i had to change the values of country and region to differentiate since the values are same in both the objects.

How to create "this" object in AngularJs?

I have a list of name's and id's. I have displayed it with ng-repeat property. I want to show the corresponding id's along with the name in 1 second on its click.
$scope.showFn = function() {
$scope.showPopup = true;
$timeout(function(){
console.log("timeout");
$scope.showPopup = false;
}, 1000);
};
I have created a plunker https://plnkr.co/edit/kvkgwp60Bxq2MrHrr5Rr?p=preview
Now showing all the id's in a single click. Please help. Thanks.
Try with below in HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="main">
<ul>
<li ng-repeat="item in items">
{{item.name}}
<span ng-show="showPopup && item.id == shownId">{{item.id}}</span>
</li>
</ul>
</body>
</html>
Controller will be like below:
var app = angular.module('app', [])
.controller('main', function($scope, $timeout) {
$scope.items = [{
"name": "one",
"id": "1"
}, {
"name": "two",
"id": "2"
}, {
"name": "three",
"id": "3"
}, {
"name": "four",
"id": "4"
}, {
"name": "five",
"id": "5"
}, {
"name": "six",
"id": "6"
}, {
"name": "seven",
"id": "7"
}]
$scope.showFn = function(Item) {
$scope.shownId = Item;
$scope.showPopup = true;
$timeout(function() {
console.log("timeout");
$scope.showPopup = false;
}, 1000);
};
});

Update document in a JSON Collection using AngularJS

I would like to update document in a JSON Collection using AngularJS
My JSON Collection:
$Scope.employee = {
"staff" :
[
{
"id" : 1,
"Name" : "John",
"email" : "john#abc.com"
},
{
"id" : 2,
"Name" : "Watson",
"email" : "watson#abc.com"
},
{
"id" : 3,
"Name" : "jack",
"email" : "jack#abc.com"
},
{
"id" : 4,
"Name" : "Jim",
"email" : "jim#abc.com"
},
{
"id" : 5,
"Name" : "Rose",
"email" : "rose#abc.com"
}
]
};
Now I need to update the document where Id = 2 to
$Scope.updateEmployee = {
"id" : 2,
"Name": "Emma",
"email": "emma#abc.com"
};
Kindly assist me how to replace a particular document and I would like to update the email of id = 5 to hr#abc.com
You can do this,
$scope.update = function(){
$scope.employee.staff.forEach(function (item) {
if (item.id == 2 ) {
item.Name = "Emma";
item.email ="emma#abc.com";
};
});
}
DEMO
$scope.updateItem = function(item) {
for (var i = 0; i < $cope.employee.staff.length; i++) {
if (item.id === $scope.employee.staff[i].id) {
$scope.employee.staff[i] = item;
break;
}
}
}
Now if you want to update $Scope.employee with id 5, just do :
$scope.updateItem({
id: 5,
Name: 'bill',
email: 'test#test.fr'
});
You can do it using underscore.js
Plunker
Basically, you should refrain from traversing your entire list because this can cause some performance related issues. What underscore.js will do is that it will return as soon as it finds an acceptable element, and doesn't traverse the entire list.
Read the official documentation here
find_.find(list, predicate, [context]) Alias: detect
Looks through each value in the list, returning the first one that passes a
truth test (predicate), or undefined if no value passes the test. The
function returns as soon as it finds an acceptable element, and
doesn't traverse the entire list.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.employee = {
"staff": [{
"id": 1,
"Name": "John",
"email": "john#abc.com"
}, {
"id": 2,
"Name": "Watson",
"email": "watson#abc.com"
}, {
"id": 3,
"Name": "jack",
"email": "jack#abc.com"
}, {
"id": 4,
"Name": "Jim",
"email": "jim#abc.com"
}, {
"id": 5,
"Name": "Rose",
"email": "rose#abc.com"
}]
};
$scope.update = function() {
var index = _.findIndex($scope.employee.staff, function(o) {
return o.id == 2;
})
$scope.employee.staff[index].Name = "Emma";
$scope.employee.staff[index].email = "emma#abc.com";
}
});
<!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.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="emp in employee.staff ">
<div>{{emp.id}} {{emp.Name}}</div>
</div>
<button ng-click="update()">
Update
</button>
</body>
</html>

bind select from api using angularJS

I'm trying to populate a Select getting data from a webapi using ng-options.
Basically, my webapi returns the following JSON:
{
"items":[
{
"name":"X",
"id":1
},
{
"name":"Y",
"id":2
}
]
}
And I Need to generate options in a select displaying the name property, but with the id as value.
The problem is that I can't display my options using ng-options. Here's what I'm trying:
<html ng-app='app'>
<head>
<title>angular</title>
</head>
<body ng-controller='DemoCtrl'>
<select ng-model="selectedTestAccount" ng-options="option.name for option in testAccounts">
<option value="">Select Account</option>
</select>
<script src='https://code.angularjs.org/1.5.0-rc.0/angular.min.js'></script>
<script>
angular.module('app', []).controller('DemoCtrl', function ($scope, $http) {
$scope.selectedTestAccount = null;
$scope.testAccounts = [];
$http({
method: 'GET',
url: '/api/values',
data: {}
}).success(function (result) {
console.log(result);
$scope.testAccounts = JSON.parse(result.items);
});
});
</script>
</body>
</html>
I hope this helps you
angular.module("app", []);
angular.module("app").controller("ctrl", function($scope) {
$scope.testAccounts = [];
var youJson = [
{ "items": [{ "name": "X", "id": "your value for X" }, { "name": "Y", "id": "your value for Y" }] },
{ "items": [{ "name": "A", "id": "your value for A" }, { "name": "B", "id": "your value for B" }] }
];
angular.forEach(youJson, function(items) {
angular.forEach(items.items, function(item) {
$scope.testAccounts.push(item);
});
});
console.log($scope.testAccounts);
});
<!doctype html>
<html ng-app="app" ng-controller="ctrl">
<head>
</head>
<body>
<select ng-model="mySelect" ng-options="item.id as item.name for item in testAccounts"></select>
{{mySelect}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-rc.0/angular.js"></script>
</body>
</html>

Augmenting JSON from REST about additional data within AngularJS

EDIT (SOLUTION): http://plnkr.co/edit/SjzpmQqMPuOCvcdZn5bV?p=preview
I get following data from a REST-API:
[
{
"a": "foo"
},
{
"a": "bar"
}
]
but need that:
[
{
"a": "foo",
"activated": false
},
{
"a": "bar",
"activated": true
}
]
how could I do that within angular, how can I principally add some new properties so that I can react on their change may be with a new style.
SECOND QUESTION: Or maybe I need following transformation:
{
"a": {
"foo": true,
"bar": false
}
}
Is there an "Angular-way" to do that? Do I have to use libraries like lodash, underscore etc.. ?
You can use underscorejs's extend method.
http://jsfiddle.net/2676saju/
<!doctype html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
</head>
<body>
<div ng-controller="MyController as vm">
{{vm.list | json}}
</div>
<script>
angular.module('app', [])
.controller('MyController', function () {
var vm = this;
var list = [{
"a": "foo"
}, {
"a": "bar"
}];
vm.list = _.each(list, function (item) {
var result = _.random(0, 100) % 2 ? true : false;
_.extend(item, { activated: result });
});
});
</script>
</body>
</html>
Result
[ { "a": "foo", "activated": false }, { "a": "bar", "activated": true } ]
array[1].c = "Michael Jackson";
array[1].d = ["Thriller..."]
and array[0].c for george michael...
For an "Angular way" solution, you can use the angular.forEach function
angular.module("myApp")
.controller("myVm", function($scope) {
var vm = $scope;
vm.items = [
{
"a": "foo"
},
{
"a": "bar"
}
];
vm.activeList = [];
var pushItem = function(value,key) {
var o = {};
o[value.a] = false;
this.push(o);
};
angular.forEach(vm.items, pushItem, vm.activeList);
});
OUTPUT
activeList = [{"foo":false},{"bar":false}]
For more information on the angular.forEach function, see the AngularJS angular.forEach API Reference

Resources