AngularJS resource return empty json - json

Part of Code:
From Service part:
$resource('/Serializer/community/V1/latestPost/:start/:end,{
},{
query: {method:'GET',
params:{start:new Date().getTime(), end:1},
isArray:true}
})
From Controller part:
Post['latestPost_timestamp'].query({start: minTime,end:1},function (data) {
alert(JSON.stringify(data));
});
Result:
From console or link open on browser:
[3993,3983,3974,3964,3954,3944,3934,3926,3920,3910]
From controller:
[{},{},{},{},{},{},{},{},{},{}]
Why it return empty {} in controller?
I would like it to be return in [3993,3983,3974,3964,3954,3944,3934,3926,3920,3910] but not
[{},{},{},{},{},{},{},{},{},{}].
Can anyone help? Thanks

That's because a $resource should be an object and not a primitive, like a number in your case. If a resource could be a primitive, then you would have a problem with being able to both do this:
var posts = Post.query({start: minTime,end:1}, function() {
for (var i = 0; i < posts.length; i++) {
var post = posts[i];
// If post here should be equal to for example 3993 in
// your JSON, you wouldn't be able to call any methods
// on it. The following two statements sort if illustrates it:
assert(post === 3993);
post.$save();
}
});
A resource is an object because of this, so you should probably change your server code to return something like [{id: 3993}, {id: 3983}, ...] instead, so that you can access the id by post.id.

Related

Unable to retrieve JSON array with AngularJS $resource

I've been trying retrieve values from JSON and so far, been unsuccessful. It does get called on the front-end when I refresh the page, but the information is not passing to the next method. I think the issue might be down to the promises.push... line, as I've tried to debug the method underneath and the information is not being passed on at all.
AngularJS:
var promises = [];
promises.push(SpringDataRestService.get({"collection": "subjects"}).$promise);
// Require each of these queries to complete before continuing
$q.all(promises).then(function (data) {
// Grab the first result
$scope.available = data[0].subjects;
$scope.selected = [];
// If this is an update, get the second result in set
if (data.length > 1) {
// For each permission that is assigned to this role, add ID (name) to selected
for (var i = 0; i < data[1].data.subjects.length; i++) {
var perm = data[1].data.subjects[i];
$scope.selected.push(perm.name);
}
}
$scope.tableEditOptions = new NgTableParams({}, {
dataset: $scope.available
});
$scope.available, 'name');
}).catch(function (data) {
// ERROR
});
JSON:
[
{
"name": "FWGWG",
"description": "WGWGWG",
"lockId": 0
},
{
"name": "QFQFQF",
"description": "QFQFQFQ",
"lockId": 0
}
]
I'm confident as well my for loop is wrong due to assigning the values as well, since I don't think it should be data.subjects, but I understand these threads are only 1 issue per question. Any help would be greatly appreicated.
Use the query method for arrays:
var promise = SpringDataRestService.query({"collection": "subjects"}).$promise;
promise.then(function (dataArr) {
console.log(dataArr);
//...
}).catch(function (errorResponse) {
console.log(errorResponse);
});
With the REST services, the get method returns a JavaScript object and the query method returns a JavaScript array.
From the Docs:
$resource Returns
A resource "class" object with methods for the default set of resource actions optionally extended with custom actions. The default set contains these actions:
{
'get': {method: 'GET'},
'save': {method: 'POST'},
'query': {method: 'GET', isArray: true},
'remove': {method: 'DELETE'},
'delete': {method: 'DELETE'}
}
...
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
For more information, see
AngularJS $resource Service API Reference

Backbone: fetching from URL in router gets undefined, but it works when collection gets JSON from a variable

From a JSON stored in a variable I can get the name of the current id from a router function called show: function(id). However, when I fetch collection from an URL instead of using a JSON variable I get an undefined TypeError.
console.log(this.collection.get(id).get('name'));
What I have seen is that when I use a JSON variable the show function works fine, but when I fetch from URL, show function executes after fetch succeed.
What I am doing wrong? Why fetching from URL gets undefined? How can I make it work?
The following code is fictional, it only shows the relevant part of my code. See the two cases at the end of the code block.
jsFiddle here
// Data 1 with variable
var heroes = [
{"id": "1", "name": "Batman"},
{"id": "2", "name": "Superman"},
];
// Data 2 from url: http://example.com/heroes.json
[
{"id": "1", "name": "Batman"},
{"id": "2", "name": "Superman"},
];
HeroesCollection = Backbone.Collection.extend({
model: HeroesModel,
url: 'http://example.com/heroes.json'
});
HeroesRouter = Backbone.Router.extend({
// I use two shows to graphic this example
routes: {
'': 'index',
':id': 'show'
},
initialize: function(options) {
this.collection = options.collection;
this.collection.fetch();
// this.collection.fetch({async:false}); this fixes my problem, but I heard it is a bad practice
},
index: function() {
},
show: function(id) {
console.log(this.collection.get(id).get('name'));
// Case #1: When Collection loads from a Variable
// id 1 returns: 'Batman'
// Case #2: When Collection fetchs from URL, id 1 returns:
// TypeError: this.collection.get(...) is undefined
}
});
// Case #1: collection loads JSON from a variable
var heroesCollection = new HeroesCollection(heroes);
// Case #2: collection loads JSON with fetch in router's initialize
// var heroesCollection = new HeroesCollection();
var heroesRouter = new HeroesRouter({collection: heroesCollection});
How about this? It's been awhile, but this seems like a better approach to what you are trying to achieve. The basic concept is that once you navigate to your show route, it will execute show. This method will create a new, empty collection, and then fetch the data for it. Along with that, we pass in a success method (as François illustrated) which will execute when the request is finished with the JSON (which creates a collection of Heros).
I believe the reason you were running into the issue with the remote data is that you were trying to access this.collection before it was populated with data from the request.
You have to remember the request is asynchronous, which mean code execution continues while the request is processing.
HeroesCollection = Backbone.Collection.extend({
model: HeroesModel,
url: 'http://example.com/heroes.json'
});
HeroesRouter = Backbone.Router.extend({
routes: {
'': 'index',
':id': 'show'
},
index: function() {
},
show: function(id) {
this.herosCollection = new HerosCollection();
this.herosCollection.fetch({
success: function(collection, response, options) {
console.log(this.get(id).get('name'));
}
});
}
});
you need to trigger the router 'show' function when the collection has ended to load.
this.collection.fetch({async:false}); fixes your problem because the whole javascript code is waiting (async:false) the ajax call to be ended before going further.
The other and best solution is to wait that your collection is fetched before you try to use the results.
Basically:
MyCollection.fetch({
success: function(model, reponse) {
// do wtv you want with the result here or trigger router show method...
}
});

Comparing user input to some fields in an array of JSON objects

I have a webserver with JSON data in it. This is what my data looks like
[
{
iduser: 1,
username: "joe",
password: "****"
},
{
iduser: 2,
username: "gina",
password: "****"
}
]
In my app I take some user input and wish to compare it to the username and password field. Here is where I check the data
.service('LoginService', function ($q, $http) {
return {
loginUser: function (name, pw) {
var deferred = $q.defer();
var promise = deferred.promise;
var user_data = $http.get("http://<my ip address>:<port>/login");
user_data.then(function ($scope, result) {
$scope.user = result.data;
})
for (var x in $scope.user) {
if (name == x.username && pw == x.password) {
deferred.resolve('Welcome ' + name + '!');
} else {
deferred.reject('Wrong credentials.');
}
}
promise.success = function (fn) {
promise.then(fn);
return promise;
}
promise.error = function (fn) {
promise.then(null, fn);
return promise;
}
return promise;
}
}
})
I am still learning angularJS and I know this is not a secure way to check the data I just want this loop to work.
My understanding of what I have here is that $scope.user holds my JSON data. Then the data is cycled through with the for loop and the user input name is compared to the field username of each iteration. But this is not the case as I am getting a fail every time.
I'm almost certain its a syntax error, but I don't know JavaScript or AngularJS well enough to find the problem. Any help is really appreciated, Thanks.
Edit 1
After what Nujabes said I made some changes since I don't need $scope.
//previous code the same
user_data.then(function (result) {
var user = result.data;
})
for (var x in user) {
if (name == x.username && pw == x.password) {
//prior code the same
I don't think var can hold the data and thats why I'm still getting errors. I think it should be in an array.
I think your syntax error is that you omit $scope.
You should inject $scope service to this line:
.service('LoginService',function($q,$http,$scope){ ...
});
And this code :
user_data.then(function ($scope, result) {
$scope.user = result.data;
});
Omit the $scope.
->
user_data.then(function (result) {
$scope.user = result.data;
});
like this.
Give it a try.
I hope it work.
(However, why do you want to use $scope service in your 'service'?
I think, defining local value and returning some method is a better choice.
and you use the $scope service in your 'controller'.)
$scope.user you are trying to loop through is array right ?
using (for/in) will store the key in the variable x which is in your case the index of each element (0,1,2,..) , to loop through arrays use (for/of) like this :
for (var value of array)
this will give you the values ...

Create a collection from inside a collection

I have a collection, which when fetched gets a json and puts into collection:
The JSON format is:
[
{
name: 'Hello',
age: '22',
bio: [{
interest: 'soccer',
music: 'r&B'
}]
}
]
I want to make another collection from bio (without fetching again).
The reason is I want to access both name, age and bio and a parse function can have only one return?
var user = new Backbone.Collection.extend({
url: '/user',
parse: function (response) {
//I want both of this?
//return response;
return response.bio;
}
});
I am passing this collection on success function of fetch into two different views.
//Controller File....
.............
mycollection.fetch({
success: function() {
//Details View wants response
PrimaryLayout.main.show(new detailsView{collection: mycoll});
//Bio View wants response.bio
PrimaryLayout.body.show(new bioView{collection: mycoll});
}
})
What would be the best way to tackle this? Can I clone a collection and just have bio in it?
I've generally solved this by instantiating the sub-collection in parse:
var User = Backbone.Model.extend({
parse: function(json) {
// instantiate the collection
json.bio = new Backbone.Collection(json.bio);
// now person.get('bio') will return a Collection object
return json;
}
});
var Users = Backbone.Collection.extend({
model: User,
// ...
});
I think this is what you are looking for : Backbone Associations. Have a look at the tutorials and examples there.

Angular JS detailed view with only one json

I'm introducing in Angular with its Tutorial "Phonecat".
Against the tutorial I'd like to build a simple app with a list and detail view with only one json, containing all informations.
The list-view (showing complete content of the json) works fine but I'm struggle with how to set my Angular services for the detail-view.
I am using the XHR method:
Controller.js:
function PlaygroundDetailCtrl($scope, Playground) {
$scope.playgrounds = Playground.query();
}
Services.js
angular.module('playgroundcatServices', ['ngResource']).
factory('Playground', function($resource){
return $resource('playgrounds/playgrounds.json', {}, {
query: {method:'GET', isArray:true}
});
});
playground.json
[
{
"id:" 1,
"properties": "true"
"lat": "51.347789"
"lon": "12.232234"
},
{
"id:" 2,
"properties": "false"
"lat": "51.347789"
"lon": "12.766667"
}
]
I want Angular to display only one entry (id:1) with its properties.
What is the smartest way to do that: showing again all and then filter?
I am stumped.
Use an Angular filter on your view (there's no need to filter the data on the service):
<div ng-repeat="entry in playgrounds | filter:{id: 1}">
<p>properties: {{entry.properties}}</p>
<p>lat: {{entry.lat}}</p>
<p>lon: {{entry.lon}}</p>
</div>
jsfiddle: http://jsfiddle.net/bmleite/Ad6u9/
This worked out quite good:
Controller:
function PlaygroundDetailCtrl($scope, $routeParams, $http) {
$http.get('playgrounds/playgrounds.json').success(function(data){
angular.forEach(data, function(item) {
if (item.id == $routeParams.playgroundId)
$scope.playground = item;
});
});
I've got exactly the same scenario now I think (I'm guessing you're developing with 'mobile' in mind (as I am and want to minimise data transfer) - I'm using one 'master json file', and then on my detail view just filtering that json file (so that the json doesn't have to be reloaded) on the ID value.
This is totally untested but your code from the original question should be modified something like this:
angular.module('playgroundcatServices', ['ngResource'])
.factory('Playground', function($resource){
return $resource('playgrounds/playgrounds.json', {}, {
query: {method:'GET', isArray:true}
});
});
function PlaygroundDetailCtrl($scope, Playground) {
Playground.query(
// params (none in this case)
{},
// Success
function (data) {
$scope.playgrounds = data.filter(function (o) {
return o.id == $routeParams.playgroundId; // assuming you've set this up in your routes definition
})[0];
},
// Error
function (data) {
//error handling goes here
}
);
}
You may want to put something like $scope.isDataLoaded = true; in your 'success' handler as well, and do a watch on that, to use to check to see when the data has finished loading (eg. for in a directive).
I'm not super happy with the [0] in there, but it think the solution is better than a forEach loop myself.