I am a new bie to angular and trying to learn it.
I am trying to display user data from a webservice that I received as response.
here's the response
{
"Users": {
"SearchTerm": "angularjs ra1",
"ResultsPerPage": "20",
"RecordStartNumber": "0",
"TotalEstimatedResults": "6",
"User": [{
"WWID": "123456",
"Email": "mary.p.wilson#yahoo.com",
"BusinessTitle": "Project Manager",
"Name": "Mary Wilson",
"firstname": "Mary",
"lastname": "Wilson",
"idsid": "RAP"
}, {
"WWID": "1234567",
"Email": "steve.r.smith#gmail.com",
"BusinessTitle": "Quality Assurance",
"Name": "Steve Smith",
"firstname": "Steve",
"lastname": "Smith",
"idsid": "DRPRESTO"
}, {
"WWID": "12345678",
"Email": "jon.jones#gmail.com",
"BusinessTitle": "Chef",
"Name": "Jon Jones",
"firstname": "Jon",
"lastname": "Jones",
"idsid": "JJONES"
}]
}
}
MyScript.js
var Application = angular.module('TestModule', []);
Application.controller('TestController', function ($scope,$http) {
$scope.TestValue = "Hello World from Controller";
$scope.Myfunc = function asdf() {
$http.get('http://unifiedcollaborationprofile.gots.com/search/expert/data/v2/?apiKey=SECRET&listFromPersonNumber=0&numPeoplePerPage=20&query=angularjs+ra1&returnFriendlyResults=true').then(
function (response) {
$scope.users = [];
angular.forEach(response.Users, function (value, key) {
$scope.users.push(value);
});
});
};
});
Page.html
<!DOCTYPE html>
<html ng-app="TestModule">
<head>
<title></title>
<meta charset="utf-8" />
</head>
{{2+3}}
<body>
<div ng-controller="TestController">
{{2+3}}
{{TestValue}}
<input type="text" ng-model="TestValue" />
<input type="button" value="Click Me To Get All Users!!!!" ng-click="Myfunc()" />
<ul ng-repeat="k in users">
<li>WWID:{{k.WWID}} Email:{{k.Email}} Name:{{k.Name}} IDSID:{{k.idsid}}</li>
</ul>
</div>
</body>
</html>
<script src="scripts/angular.min.js"></script>
<script src="scripts/MyScripts/MyScript.js"></script>
But nothing gets rendered on my Page.
I am not sure if I am rightly accessing the nested User object in Users Collection of JSON and its properties.
what am I missing.
I've created plunker with your code and all I did to make it work is to change it to this:
$scope.Myfunc = function asdf() {
$http.get('test.json').then(function(response) {
$scope.users = [];
angular.forEach(response.data.Users.User, function(value, key) {
$scope.users.push(value);
});
});
};
http://plnkr.co/edit/Fu1tCnhxSn9dgBXtTJ9r?p=preview
You must remember that then after http promise gets resolved receives an object that contains several values: status code, headers and data that will contain your data
I think problem is here
$scope.users = [];
angular.forEach(response.Users, function (value, key) {
$scope.users.push(value);
});
try change to
$scope.users = response.data.Users
or you can change to
$scope.users = [];
angular.forEach(response.data.Users, function (value, key) {
$scope.users.push(value);
});
angular.forEach(response.Users.User, function (value, key) {
$scope.users.push(value);
});
your array is nested so you have to call the array in the object
Related
I am facing some issue while returning value from angular forEach.
Here is my data:
vm.memberDetails={
"member": [
{
"firstName": "HARRY UTTWO",
"lastName": "POTTER",
}
],
"User": [
{
"memberId": 7586671,
"customerId": 7586671,
"customerStatus": "T",
"firstName": "HEMOOINE",
"lastName": "POTTER",
},
]
}
vm.mockData = {
"data": [{
"memberNo": 7586671,
"suffix": "A"
}]
}
Here I need to compare memberId and get name from first data.I used angular.forEach but for name i need to use
vm.memberDetails.User[0].firstName but it return only on value with looping.
Controller:
angular.forEach(vm.memberDetails.User, function (value1,key1) {
angular.forEach(vm.mockData, function (value2,key2) {
if (value1.memberId === value2.memberNo) {
vm.some= vm.memberDetails.User[0].firstName;
}
});
});
return vm.some;
Any help would be appreciated.
Thanks.
It looks like you need to grab the data array from vm.mockData so change the line angular.forEach(vm.mockData, function (value2,key2) { into angular.forEach(vm.mockData.data, function (value2,key2) {
angular.forEach(vm.memberDetails.User, function (value1,key1) {
angular.forEach(vm.mockData.data, function (value2,key2) {
if (value1.memberId === value2.memberNo) {
vm.some= vm.memberDetails.User[0].firstName;
}
});
});
return vm.some;
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title></title>
</head>
<body ng-controller="mCon">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.7/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module('myApp', []);
app.controller('mCon', function(){
var vm = this;
vm.memberDetails = {
"member": [{
"firstName": "HARRY UTTWO",
"lastName": "POTTER",
}],
"User": [{
"memberId": 7586671,
"customerId": 7586671,
"customerStatus": "T",
"firstName": "HEMOOINE",
"lastName": "POTTER",
}, ]
}
vm.mockData = {
"data": [{
"memberNo": 7586671,
"suffix": "A",
}
]
}
angular.forEach(vm.memberDetails.User, function (value1,key1) {
angular.forEach(vm.mockData.data, function (value2,key2) {
if (value1.memberId === value2.memberNo) {
vm.some= vm.memberDetails.User[0].firstName;
}
});
});
return vm.some;
})
</script>
</body>
</html>
Unfortunately I have no control on how the API returns data. I get what I get :/
I need help getting my data formatted correctly or possibly using a custom pipe to display it correctly. I've tried different things (mergeMap, filter, group by pipe, etc), but I can't seem to get exactly what I want. Any help would be appreciated.
Sample data
[
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo1.jpg", "photoTitle": "Photo1"},
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo2.jpg", "photoTitle": "Photo2"},
{ "id": "rogersfr02", "first": "Fred", "last": "Rogers", "photo": "photo55.jpg", "photoTitle": "Photo55"},
...
]
Component
this.searchService.getData().subscribe(searchResults => {
this.searchResults = searchResults;
....? transform data here or custom pipe in template
});
Desired result (show name once and then all associated photos)
Bob Ross
Photo1
Photo2
Fred Rogers
Photo55
...
What is the most efficient way to get the output I'm looking for? Thanks in advance!
The following code is my pure RxJS solution :P
import { from } from 'rxjs';
import { groupBy, mergeMap, map, toArray, tap } from 'rxjs/operators';
let searchResults = [
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo1.jpg", "photoTitle": "Photo1"},
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo2.jpg", "photoTitle": "Photo2"},
{ "id": "rogersfr02", "first": "Fred", "last": "Rogers", "photo": "photo55.jpg", "photoTitle": "Photo55"}
];
from(this.searchResults).pipe(
// Select necessary attributes
map(result => {
//console.log('Result:', result);
let fname = result['first'];
let lname = result['last'];
let photo = result['photoTitle'];
let rname = [fname, lname].join(' ');
return { rname, photo };
}),
// group objects by `rname` attribute
groupBy(result => result['rname']),
// return each item in group as array
mergeMap(group => {
//console.log('Group $1:', group);
return group.pipe(
toArray(),
);
}),
// Reduce arrays of objects
map(group => {
//console.log('Group $2:', JSON.stringify(group));
let rname = group[0]['rname'];
return group.reduce((a, b) => {
return {
rname: rname,
photo: [a.photo, b.photo],
};
});
}),
// Bypass and verify results
tap(result => console.log('Result:', result)),
).subscribe();
You can possibly use loadash's groupBy and toPairs functions to group your array data based of on the user's firstname and lastname like below:-
var users = [
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo1.jpg", "photoTitle": "Photo1"},
{ "id": "rossbo01", "first": "Bob", "last": "Ross", "photo": "photo2.jpg", "photoTitle": "Photo2"},
{ "id": "rogersfr02", "first": "Fred", "last": "Rogers", "photo": "photo55.jpg", "photoTitle": "Photo55"}
]
var result = _.groupBy(users, (user)=> user.first + ' ' + user.last);
result = _.toPairs(result);
console.log('Result: ', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
You can either format or create your own custom pipe based on the function above.
You can refer to the following stackblitz to see a working Angular solution.
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 made a filter for the field DataIscr on this json :
[
{
"IdPers": "1067",
"CognNome": "JANE SMITH",
"Sex": "F",
"DataIscr": "1949-12-29T00:00:00+01:00"
},
{
"IdPers": "1093",
"CognNome": "JOHN SMITH",
"Sex": "M",
"DataIscr": "1969-12-02T00:00:00+01:00"
},
{
"IdPers": "1093",
"CognNome": "JANE SMITH",
"Sex": "F",
"DataIscr": "1969-06-17T00:00:00+01:00"
}
]
and I used the format date: 'yyyy' to display only the year:
<label for="DataIscr">DataIscr:</label>
<select style="width:200px" data-ng-options="Person.DataIscr as Person.DataIscr|date:'yyyy' for Person in OutAnagrafica" id="DataIscr" data-ng-model="filter.DataIscr" class="form-control input-sm"></select>
plunker:http://plnkr.co/edit/ED1v7czBosNSpCYxKW7n?p=preview
How can I delete the duplicates?? I want to filter object with the same year and the filter 'unique' from angular Ui doesn't work. How can I do??
Sidos Check this out , i used 'angular.filter' modules unique filter .
<select style="width:200px" data-ng-options="Person for Person in OutAnagrafica| removeDuplicates " id="DataIscr" data-ng-model="filter.DataIscr" class="form-control input-sm"></select>
App.filter('removeDuplicates', function ($filter) {
return function (input) {
var dates=[];
angular.forEach(input,function(item,index)
{
dates.push($filter('date')(item.DataIscr,'yyyy'));
})
console.log(dates);
return $filter('unique')(dates);
};
});
http://embed.plnkr.co/slrtdv/preview
Instead of using the angular ui filter, write your own custom filter for filtering the date values. since the UI filter check for the whole value, it does not support the format the values for duplicate removal. below is the fiddle link for your scenario.
JS
var app = angular.module('myApp', []);
app.controller('OutAnCtrl', function ($scope) {
$scope.OutAnagrafica = [{
"IdPers": "1067",
"CognNome": "JANE SMITH",
"Sex": "F",
"DataIscr": "1949-12-29T00:00:00+01:00"
}, {
"IdPers": "1093",
"CognNome": "JOHN SMITH",
"Sex": "M",
"DataIscr": "1969-12-02T00:00:00+01:00"
}, {
"IdPers": "1093",
"CognNome": "JANE SMITH",
"Sex": "F",
"DataIscr": "1969-06-17T00:00:00+01:00"
}];
});
app.filter('customDateUnique', function ($filter) {
return function (arr, field) {
return _.uniq(arr, function (a) {
return $filter('date')(a.DataIscr, 'yyyy');
});
};
});
HTML
<body>
<div>
<div data-ng-controller="OutAnCtrl">
<label for="DataIscr">DataIscr:</label>
<select style="width:200px" data-ng-options="Person.DataIscr as Person.DataIscr|date:'yyyy' for Person in OutAnagrafica | customDateUnique" id="DataIscr" data-ng-model="filter.DataIscr" class="form-control input-sm"></select>
</div>
</div>
</body>
http://jsfiddle.net/1tw3zg9s/1/
After seeing your comment, I changed my answer.
You can define a new $scope.filtered array and upon ajax success do:
$http.get('OutAnagrafica.json')
.success(function (data) {
$scope.OutAnagrafica = data;
$scope.OutAnagrafica.forEach(function(item) {
if (yearUnique($scope.filtered, item)) {
$scope.filtered.push(item);
}
});
});
And you have the function yearUnique:
function yearUnique(arr, item) {
var year = item.DataIscr.substring(0, 4);
var res = true;
if (arr.forEach(function(i) {
if (i.DataIscr.indexOf(year) > -1) {
console.log('false');
res = false;
}
}));
return res;
}
And on the HTML:
<tr data-ng-repeat="Person in filtered">
...
</tr>
Plunker
Imagine the following JSON API:
[
{
"id": "1",
"name": "Super Cateogry",
"products": [
{
"id": "20",
"name": "Teste Product 1"
},
{
"id": "21",
"name": "Teste Product 2"
},
{
"id": "22",
"name": "Teste Product 3"
}
]
}
]
Is there anyway for me to only return the products array with Angularjs?
I have a simple service calling the JSON:
services.factory("ProductService", function($http) {
return {
"getProducts": function() {
return $http.get("/product/index");
}
};
});
That is being called in the controller like so:
components.success(function(data) {
$scope.products = data;
});
But it returns the whole JSON as expected, I need it to return only the "products" array so I can iterate through it.
PS: This is merely a simple example to illustrate the problem, I realize that I could change the API to fit my needs in this case, but that's not the point.
You would just assign the products array to your scope property...
components.success(function(data) {
$scope.products = data[0].products;
});
You could customize it via a promise, and do it yourself.
"getProducts": function() {
var promise = $q.defer();
$http.get("/product/index").success(function(data){
promise.resolve(data && data.products);
}).error(function(msg){
promise.reject(msg);
})
return promise.promise;
}
How to use:
getProducts().then(
function(data) {
$scope.products = data;
},
function(msg){
alert('error')
}
);