I am trying to read data from services using restful service. when I have one json object I am getting the issue. here is my code:
service code:
var ROAList =[];
var promise = $http.post(urlBase + '/' + 'getROAList', params)
.success(function (data) {
ROAList = data.item;
return ROAList;
})
.error(function (data) {
ROAList = 'error';
return ROAList;
});
return promise;
In Controller:
var list =[];
$scope.ROAListItem = function(){
list =service.getROAList();
}
In html:
<div ng-repeat="roa in list()" ng-click ="selectROAitem(roa.soa.name)">
<div> {{roa.id}} </div>
<div> {{roa.soa.name}}</div>
here is my json data:
{"item": [
{
"id":"001",
"type":"001x2z"
"sao": {
"itemNo": "3",
"name": "001"
},
},
{
"id":"002",
"type":"002x2g"
"sao": {
"itemNo": "5",
"name": "006"
}
]}
it working fine for more than one item but I am getting an error for one item. for this json data:
{"item":{
"id":"001",
"type":"001x2z"
"sao": {
"itemNo": "3",
"name": "001"
}
}
for this data ,I am getting 'cannot read property 'name' of undefined.
Removed long winded answer. I didn't see your last section. Your multiple returns are all stored in an array, while your single return is not. So the dot access is incorrect for the single object.
In response to comment: again, you should really format the return data so that it's always in array, but otherwise you could do something like:
$scope.ROAListItem = function(){
list = service.getROAList();
if(!Array.isArray(list)){
list = [list];
}
}
A quick solution would be to modify your service call like so:
$http.post(urlBase + '/' + 'getROAList', params)
.success(function (data) {
ROAList = data.item;
if (!angular.isArray(ROAList)) {
ROAList = [ ROAList ];
}
return ROAList;
})
However, your service really should provide consistent behavior, returning an array even if there is only one item.
Related
I have 3 components, the web api, the controller, and the html. I can hit the web api just fine and i get back the results in JSON format, but when it then tries to render the JSON into the html, it looks like this.
{
"Projects": [{
"ProjectId": 1,
"Name": "Project1",
"Key": "Software",
"ProjectTypeKey": "1"
}, {
"ProjectId": 2,
"Name": "Project2",
"Key": "Hardware",
"ProjectTypeKey": "2"
}, {
"ProjectId": 3,
"Name": "Project3",
"Key": "Hardware",
"ProjectTypeKey": "3"
}]
}
WebApi
public IHttpActionResult Get()
{
listProjects.Add(new Project { ProjectId = 1, Name = "Project1", Key = "Software", ProjectTypeKey = "1" });
listProjects.Add(new Project { ProjectId = 2, Name = "Project2", Key = "Hardware", ProjectTypeKey = "2" });
listEmployeeProject.Add(new EmployeeProject {Projects = listProjects });
return Json(listEmployeeProject);
}
Controller
var myApp = angular.module('myApp', []);
myApp.service('dataService', function ($http) {
this.getData = function () {
// $http() returns a $promise that we can add handlers with .then()
return $http({
method: 'GET',
url: '/api/employee'
});
}
});
myApp.controller('ProjectController', function ($scope, dataService) {
$scope.Projects = [];
dataService.getData().then(function (result) {
$scope.Projects = result.data;
});
});
HTML
<div ng-app="myApp" ng-controller="ProjectController">
{{1 + 1}}
<div ng-repeat="project in Projects">
{{project}}
</div>
Even when i switch {{project}} to {{project.Name}}, nothing renders on the page.
console.log(results.data) looks like below
Its very clear from your console that you are returning an array of length 1 which has another array of length 3 in it
This is because of this line in your code
listEmployeeProject.Add(new EmployeeProject {Projects = listProjects });
Here you are retuning a EmployeeProject array and each element of that array has multiple projects. So do either of these things
a. Return listProjects like return Json(listProjects) (You should be returning Ok(model) ideally)
b. Or in angular promise do,
$scope.Projects = result.data[0].Projects;
I am new to Angular and need to download data into a service. It works fine with local json file; however, obviously you want to get the data from another URL which then gives the issue of cross domain download. Is there a way to go around this? I need to download the data from here http://files.parsetfss.com/c2e487f5-5d96-43ce-a423-3cf3f63d9c5e/tfss-31564b7d-6386-4e86-97c5-cca3ffe988f3-phones.json rather than 'phones/phones.json' below.
'use strict';
/* Services */
function makeArray(Type) {
return function(response) {
var list = [];
angular.forEach(response.data, function(data) {
list.push(new Type(data));
});
return list;
}
}
function instantiate(Type) {
return function(response) {
return new Type(response.data);
}
}
angular.module('phonecatServices', []).
factory('Phone', function($http){
var Phone = function(data){
angular.copy(data, this);
};
Phone.query = function() {
return $http.get('phones/phones.json').then(makeArray(Phone));
}
Phone.get = function(id) {
return $http.get('phones/' + id + '.json').then(instantiate(Phone));
}
// Put other business logic on Phone here
return Phone;
});
Can this be put in the following query from parse.com (how can I write the http request bit to fit into Angular.
var query = new Parse.Query("coursesParse");
query.find({
success: function(results) {
},
error: function(error) {
}
});
You can do it this way.
Phone.query = function() {
var query = new Parse.Query("test");
query.find({
success: function(results) {
//makeArray(Phone(results));
for (var i = 0; i < results.length; i++) {
var object = {
"age": results[i].get('age'),
"carrier": results[i].get('carrier'),
"id": results[i].get('id1'),
"imageUrl": results[i].get('imageUrl'),
"name": results[i].get('name'),
"snippet": results[i].get('snippet')
};
makeArray(Phone(object));
}
},
error: function(error) {
}
});
}
I have the following code and after the first query the response data is undefined? Does anyone know the reason behind this?
--- json data ---
{
"weddings": [
{
"id": "1",
"name": "D",
"currency": [
{"USD": "10"},
{"KHR": "20000"}
],
"date": "12/12/2012",
"place": "Bopha Tep",
"paid": false
},
{
"id": 2,
"name": "C",
"currency": [
{"USD": "10"},
{"THB": "200"}
],
"date": "13/12/2012",
"place": "Bopha Charkasamrong",
"paid": false
},
{
"id": 3,
"name": "A",
"currency": [
{"KHR": "10000"},
{"THB": "200"}
],
"date": "14/12/2012",
"place": "Bopha Charkasamrong",
"paid": false
},
{
"id": 4,
"name": "B",
"currency": [
{"KHR": "20000"},
{"THB": "100"},
{"USD": "20"}
],
"date": "15/12/2012",
"place": "Bopha Charkasamrong",
"paid": false
}
]
}
--- Factory ---
.factory('WeddingService',['$resource',function($resource){
var path = 'app/scripts/factories/data/weddings.json';
var data;
var resource = $resource(path,{},{
query: { method: "GET", isArray: false }
});
var weddings = function(){
resource.query().$promise.then(function(response){
data = response.weddings;
});
return data;
}
return {
list: function(){
if(data){
console.log("returning cached data");
return data;
}else{
console.log("getting countries from server");
return weddings();
}
},
get: function(find_id){
return _.findWhere(this.list(),{id:find_id});
},
}
}])
--- Controller ---
$scope.weddings = wedding.list();
console.log($scope.weddings);
---Log---
getting countries from server
undefined
Fetching the data from the server is async so you need to use the promise from the resource to know when the data has been resolved and to get the data. See https://docs.angularjs.org/api/ngResource/service/$resource specifically search for $promise also see this other SO post:
AngularJS resource promise
Forgot about this post but
.factory('WeddingService',['$resource',function($resource){
var path = 'app/scripts/factories/data/weddings.json';
var data;
var resource = $resource(path,{},{
query: { method: "GET", isArray: false }
});
var weddings = function(){
//this will return the promise from the call to .then
return resource.query().$promise.then(function(response){
data = response.weddings;
});
}
return {
list: function(){
if(data){
console.log("returning cached data");
return $q.when(data); // return a promise to keep it consistent
}else{
console.log("getting countries from server");
return weddings();
}
},
get: function(find_id){
return _.findWhere(this.list(),{id:find_id});
},
}
}])
controller
wedding.list().then(function(data){
$scope.weddings = data;
console.log(data);
});
In reality I'd typically just make a reference to WeddingService from the scope or controller definition and access the data through the factory in most cases, but having the setup to return a promise for the data works well to expose the async nature of the request.
It seems you are using data before it is set
var weddings = function(){
resource.query().$promise.then(function(response){
data = response.weddings;
});
// data is not set until the query above is completed
return data;
}
You need to either return the promise and wait for that when using the code, or use the $broadcast('event'); and $on('event', function() { }) event system to trigger your other code when the data is downloaded completely.
You can use the first option like the following:
var weddings = function(){
data = resource.query(function(result) {
console.log('wedding is set to ', result);
},
function(error) {
console.error('something went wrong ', error);
});
return data;
}
Now in your code that uses weddings() you can use $promise to wait for the data and if the query is complete, you can use data like you normally would.
When using bindings from angular html you can also use data directly, since the view will be updated when the data is downloaded.
I have an $http request going out and fetching some JSON that is being returned in a structure like this:
{
"news": [
{
"item1": "information1",
"item2": "information2",
"item3": "information3",
"itemId": "ID1"
},
{
"item1": "information1",
"item2": "information2",
"item3": "information3",
"itemId": "ID2"
},
{
"item1": "information1",
"item2": "information2",
"item3": "information3",
"itemId": "ID3"
},
]
}
Now, I can use ng-repeat to get to the news items just fine, but I need to make another $http request with the ID that is nested in each news item. Basically, I need to use that ID to find a name so that my news items are no longer just bits of information with an ugly ID, but bits of information with a user-friendly name. I already have the code returning, what I think, is the ID for each of those news items:
$http.jsonp('http://website/api/news&jsonp=JSON_CALLBACK')
.success(function (result) {
$scope.news = result.news;
$scope.items = [];
angular.forEach(result.news, function (item, index) {
$scope.items.push(item);
$http.jsonp('http://website/api/' + $scope.items.itemId + '?jsonp=JSON_CALLBACK')
.success(function (result) {
$scope.fullItem = result.data;
})
.error(function () {
$log.warn("Something broke.");
});
});
})
.error(function () {
$log.warn("Something broke.");
});
As always, any help you all could provide would be very much appreciated.
I am trying to grab just few ids from json and not the complete payload of json. Is that possible? here is my code
Car.controller('IndexCtrl', function ($scope, CarRestangular) {
$scope.cars = CarRestangular.all('car').getList();
});
here is my json
[
{
"id": 1,
"name": "Mike",
},
{
"id": 2,
"name": "Floyd",
},
{
"id": 3,
"name": "Roy",
},
{
"id": 4,
"name": "Roy",
},
]
I want to get records where ids are 2 and 4. How could I do that. Also if possible, what would I need to do to get top two records in an other case that I would need.
Thanks
The newer versions of angular don't automatically unproxy promises in scope. Therefore you can't immediatelt do:
$scope.cars = CarRestangular.all('car').getList();
But you have to do:
CarRestangular.all('car').getList().then(function(result){
$scope.cars = result;
));
The filtering would be the best if you have lodash included.
https://gist.github.com/lc-nyovchev/7414166e4dbf2dfbc908
You define a service with a method that does the filtering for you:
.factory('SomeService',['$q', 'Restangular', function($q,Restangular){
return {
someMethod: function(){
var deferred = $q.defer();
Restangular.all('car').getList().then(function(results){
var filtered = _.filter(results, function(result){
return result.id === 2 || result.id === 4;
});
return deferred.promise;
}
};
}])
Then you use the service in your controller:
.controller('YourController', ['SomeService', function(SomeService){
SomeService.someMethod().then(function(filteredResult){
$scope.cars = filteredResult;
});
}]);
Alternatively you can just do:
CarRestangular.all('car').getList().then(function(results){
$scope.cars = _.filter(results, function(result){
return result.id === 2 || result.id === 4;
});
});
Edit: all those answers assume you want to do the filtering client side. IF your backend supports it, you can do something like:
CarRestangular.all('car').getList(id:[2,4]).then(function(result){
$scope.cars = result;
));
And if your backend is written in such a way that is supports filtering on the id attribute, it would return you the correct results and you wouldn't have to filter them.