ngResource return a singular item - angularjs

When trying to return a singular item from a mongoDB I keep getting an error telling me I am returning an array as apposed to an object. Here's my service code:
resource: $resource('http://localhost:8080/api/item/:itemId', null, {'get' : {method: 'GET'}}, {stripTrailingSlashes: false})
function getItem(itemId) {
return this.resource.get({itemId: itemId}).$promise.then(function(resource){
return resource;
});
}
The service is above is called resolve like so:
.state('cocktail', {
templateUrl: 'client/app/features/item/item/item.html',
controller: 'ItemController',
controllerAs: 'vm',
data:{
title: 'Item'
},
params:{
itemId: null
},
resolve:{
item: getItem
}
function getItem($stateParams, itemService) {
return itemService.getItem($stateParams.itemId);
}
Then in my controller:
ItemController.$inject = ['itemService', 'item'];
function ItemController(itemService, item) {
var vm = this;
vm.item = item;
}
The object that is returned in the call is:
[
{
"_id": "57586f25661d33fe21057866",
"name": "Red Velvet",
"description": "Red Velvet Description here",
"image": "red-velvet",
"__v": 0,
"gred": []
},{
"_id": "57586f25661d33fe21057884",
"name": "Red Item",
"description": "Red Velvet Item here",
"image": "red-velvet-item",
"__v": 0,
"gred": []
},
]
The error I get in my console is - [$resource:badcfg] Error in resource configuration for action get. Expected response to contain an object but got an array. I am not expecting an array but the object of the ID I pass through in the resolve. If anyone has any comments or can see what I'm doing wrong please let me know! This is bugging me and I know it's going to be a simple fix haha!

Related

angularjs undefined resource

I am new in angularJs, I am trying to have my first steps in developping an application and I am facing a problem.
I am calling an external resource that return an object json via $resource.get(), in the callBack I am getting the correct values, but in the service the values are undefined, the problem is when I am printing the resource in the console the result has the correct values.
my json object :
{
"readOnly": false,
"questions": [
{
"questionId": "0",
"questionTitle": "question0",
"isMondatory": true,
"responseList": [
{
"questionId": "0",
"questionTitle": null,
"responseId": "00",
"responseTitle": "response00"
},
{
"questionId": "0",
"questionTitle": null,
"responseId": "01",
"responseTitle": "response01"
},
{
"questionId": "0",
"questionTitle": null,
"responseId": "02",
"responseTitle": "response02"
},
{
"questionId": "0",
"questionTitle": null,
"responseId": "03",
"responseTitle": "response03"
}
]
},
{
"questionId": "1",
"questionTitle": "question1",
"isMondatory": true,
"responseList": [
{
"questionId": "1",
"questionTitle": null,
"responseId": "10",
"responseTitle": "response10"
},
{
"questionId": "1",
"questionTitle": null,
"responseId": "11",
"responseTitle": "response11"
},
{
"questionId": "1",
"questionTitle": null,
"responseId": "12",
"responseTitle": "response12"
},
{
"questionId": "1",
"questionTitle": null,
"responseId": "13",
"responseTitle": "response13"
}
]
}
my controller is
app.controller('mycontroller', function ($scope,myservice) {
$scope.infos = null;
$scope.infos = myservice.getInfo();
}
my service is :
angular.module('xxxx').factory('myservice', function($window,$resource,$routeParams,$http,apicallservice) {
// Public API here
return {
getInfo : function(){
var result=null;
var url = "myUrl";
result = apicallservice.GetApiCall(url,$routeParams);
console.log(result.readOnly); // print undefined => KO
return result;
},
//.... other functions
my apicallservice :
angular.module('xxxx')
.factory('apicallservice', function ($http,$resource) {
var result;
// Public API here
return {
GetApiCall: function (url,obj) {
// resource
var resource = $resource(url,{param1:obj});
// cal the api
result = resource.get(function(callBack) {
console.log(callBack.readOnly); => print false => OK
return callBack;
}, function(error) {
console.log(error);
return error;
});
return result;
},
PostApiCall : function(url,obj){
result = $http.post(url,obj).then(
function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
}
};
});
please can you help me ?
thanks in advance.
From angularjs api documentation for $resource
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. This is a useful trick
since usually the resource is assigned to a model which is then
rendered by the view. Having an empty object results in no rendering,
once the data arrives from the server then the object is populated
with the data and the view automatically re-renders itself showing the
new data. This means that in most cases one never has to write a
callback function for the action methods.
So basically for
$scope.infos = myservice.getInfo();,
result will have an empty object/array reference. Since the call is asynchronous, the next line(console.log(result.readOnly)) gets called immediately and you will get undefined. Only when the underlying get/post call actually completes, variable result will be populated with the value from the server
I found what was going wrong, in the controller I had to add then() :
instead of this :
app.controller('mycontroller', function ($scope,myservice) {
$scope.infos = null;
$scope.infos = myservice.getInfo();
}
do this :
app.controller('mycontroller', function ($scope,myservice) {
$scope.infos = null;
myservice.getInfo().then(function(data) {
$scope.infos = data;
});
}
this resolved the problem.

Error in routing with id parameter, link works but displays no data

I am having an issue with retrieving the stored data (within MongoDB) by way of an :id parameter. The link works and takes me to the specified url (./contests/1), but the data doesn't show up. When querying within the mongo CMD with (db.contests.find( {id:1} )) the correct object's data is displayed correctly.
route/contest.js
router.route("/contests/:id")
.get(function(req, res, next) {
Contest.findOne({id: req.params.id}, function(err, contest) {
if(err) {
res.send(err);
}
res.json(contest);
});
service/contestService.js
app.factory("contestService", ["$http", "$resource",
function($http, $resource)
{
var o = {
contests: []
};
function getAll() {
return $http.get("/contests").then(function(res) {
angular.copy(res.data, o.contests);
});
}
function get(id) {
return $resource('/contests/:id');
}
o.getAll = getAll;
o.get = get;
return o;
}]);
})();
controller/contestController.js
var app = angular.module("sportsApp.controllers.contest,["ui.router"]);
app.config(["$stateProvider", function($stateProvider) {
$stateProvider.state("contest", {
parent: "root",
url: "/contests/:id",
views: {
"container#": {
templateUrl: "partials/contests",
controller: "ContestController"
}
}
});
}
]);
app.controller("ContestController", ["$scope","contestService", "$stateParams", function($scope, contestService, $stateParams) {
var contest_id = $stateParams.id;
$scope.contest = contestService.get({id: contest_id});
}]);
})();
Contest Schema
var mongoose = require("mongoose");
var ContestSchema = new mongoose.Schema(
{
id: Number,
tags: String,
matchups: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Matchup"
}],
usersWhoJoined: [{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}]
});
mongoose.model("Contest", ContestSchema);
Any assistance or advice would be much appreciated due to the fact that I am learning as I go with the MEAN stack and have little to no experience with it.
I am looking to display the specific contest's matchups in which displays two teams and other variables. This is my json file that I mongoimported in order to create the object of the contests collection within MongoDB:
{
"id": 1,
"tags": "NBA",
"matchups": [{
"matchupId": 1,
"selectedTeam": "",
"matchupWinner": "Atlanta",
"nbaTeams": [{
"team": "Portland",
"logo": "stylesheets/nbalogos/Portland-Trail-Blazers-Logo.png"
}, {
"team": "Atlanta",
"logo": "stylesheets/nbalogos/atl-hawks.png"
}]
}, {
"matchupId": 2,
"selectedTeam": "",
"matchupWinner": "Dallas",
"nbaTeams": [{
"team": "Dallas",
"logo": "stylesheets/nbalogos/Dallas-Mavericks.png"
}, {
"team": "Detroit",
"logo": "stylesheets/nbalogos/DET.png"
}]
}, {
"matchupId": 3,
"selectedTeam": "",
"matchupWinner": "Golden State",
"nbaTeams": [{
"team": "Golden State",
"logo": "stylesheets/nbalogos/GSW.png"
}, {
"team": "Memphis",
"logo": "stylesheets/nbalogos/Memphis-Grizzlies.png"
}]
}, {
"matchupId": 4,
"selectedTeam": "",
"matchupWinner": "Oklahoma City",
"nbaTeams": [{
"team": "Oklahoma City",
"logo": "stylesheets/nbalogos/OKC-Thunder.png"
}, {
"team": "Pheonix",
"logo": "stylesheets/nbalogos/Pheonix-Suns.jpg"
}]
}, {
"matchupId": 5,
"selectedTeam": "",
"matchupWinner": "Utah",
"nbaTeams": [{
"team": "Sacremento",
"logo": "stylesheets/nbalogos/Sacremento-Kings.jpg"
}, {
"team": "Utah",
"logo": "stylesheets/nbalogos/Utah-Jazz.jpg"
}]
}]
}
I want to create each contest in this format.
I have no idea what relevance the actual data has to this issue, so let's start with $scope.contest, since there seems to be a problem with the way you're accessing data.
// ContestController
$scope.contest = contestService.get({id: contest_id});
OK, so you're calling the contestService.get method with an object, let's say it's {id: 2}. Let's look at that method and call it with that object.
// contestService
function get(id) {
return $resource('/contests/' + id);
}
If using our dummy data, if you call get({id: 2}), you now have an Angular resource at the URL /contests/[object Object] because your object gets converted into a string. Your method would work if called using the value at the id property of that object, like:
// ContestController
$scope.contest = contestService.get(contest_id);

how do take last value from one property in JSON in angularjs

so I have chatting application, with this JSON:
{
"561c": [{
"from": "561c",
"fromname": "ryan",
"to": "sasa",
"messgae": "hey"
}, {
"from": "5512",
"fromname": "sasa",
"to": "ryan",
"messgae": "hey too"
}]
}
but this JSON will always add up when the users send messages. I want to take the the last value just from "message" to use this value in my Text-to-Speech code, how do I write the code?
and this is my Text-to-Speech:
$scope.speakText = function() {
TTS.speak({
text: ***this place is for the code***,
locale: 'en-GB',
rate: 0.75
}, function () {
// handle the succes case
}, function (reason) {
// Handle the error case
});
};
use forEach loop on the object '561c' like
var messArray = [];
561c.forEach(function(obj){
messArray.push(obj.message)})
var text = messArray.join();
You will have all the message in messArray.
If i have understood your question correct.
//get the last element of array
var lastIndex = 561c.length();
var lastObj = 561c[lastIndex];
//get message from last object of array 561c
var lastMessage = lastObj.message;
and you got what you want(y);
You can use the "pluck" function of underscore.js - http://underscorejs.org/#pluck
_.pluck(your array of JSONs, 'messgae');
You can pass $scope to your function then pass 561c you will get object then you can index message in it
Example :
$scope.chat = {
"561c": [{
"from": "561c",
"fromname": "ryan",
"to": "sasa",
"messgae": "hey"
}, {
"from": "5512",
"fromname": "sasa",
"to": "ryan",
"messgae": "hey too"
}]
}
angular.module('app',[]).controller('myctrl', function($scope, data){
$scope.561c = data.messgae;
}

Angular JS $scope $resource & Directive - Directive Loading faster than scope thus cant see data

I am using an API to load (Data) to my $scope resource, and I took an example from a directive online to create a treeview. Recursive Tree View Example
However I am changing a few things to load data from an API. Please note the commented data... when I uncomment my data everything works great, however when I use $scope.treeFamily = TreeView.query() I think there is a delay between the directive executing and me getting no data. Any insight will be helpful. Thank you!
var module = angular.module("module", ["ngResource", "ngRoute"]);
module.factory('TreeView', function ($resource) {
return $resource('/api/TreeView/:Id', {}, {
//show: { method: 'GET', isArray: true }, //<--- need to do query instead of show....
query: { method: 'GET', isArray: false},
update: { method: 'PUT', params: { id: '#id' } },
delete: { method: 'DELETE', params: { id: '#id' } }
})
});
module.controller('TreeCtrl', function ($scope, TreeView) {
$scope.treeFamily = TreeView.query();
//$scope.treeFamily = {
// name: "Parent",
// children: [{
// name: "Child1",
// children: [{
// name: "Grandchild1",
// children: []
// }, {
// name: "Grandchild2",
// children: []
// }, {
// name: "Grandchild3",
// children: []
// }]
// }, {
// name: "Child2",
// children: []
// }]
//};
});
module.factory('RecursionHelper', ['$compile', function ($compile) {
var RecursionHelper = {
compile: function (element) {
var contents = element.contents().remove();
var compiledContents;
return function (scope, element) {
if (!compiledContents) {
compiledContents = $compile(contents);
}
compiledContents(scope, function (clone) {
element.append(clone);
});
};
}
};
return RecursionHelper;
}]);
module.directive("tree", function (RecursionHelper) {
return {
restrict: "E",
scope: { family: '=' },
template:
'<p>{{ family.name }}</p>' +
'<ul>' +
'<li ng-repeat="child in family.children">' +
'<tree family="child"></tree>' +
'</li>' +
'</ul>',
compile: function (element) {
return RecursionHelper.compile(element);
}
};
});
The Result from what i get there using the following HTML.
<!DOCTYPE html>
<html lang="en" ng-app="module">
<head>
<title></title>
</head>
<body>
<div class="container">
<div ng-controller="TreeCtrl">
<table>
<tr>
<th>Name</th>
</tr>
<tr ng-repeat="result in treeFamily">
<td> From Table: {{result.name}}</td>
</tr>
</table>
<tree family="treeFamily"></tree>
</div>
<div ng-view=""></div>
</div>
Result :
Name
From Table: Parent
HOWEVER, this is from the the ng-repeat within my table, so i know the API is sending DATA and it is readable.
{
ID: "1",
type: "Folder",
name: "Parent",
children: []
}
The problem is that it seems that the directive is not loading this data.... If however uncomment the built in data I have for that scope it works fine...
I have a feeling that my directive is loading faster than my API call so I get no data. Am i doing something wrong?
Any help will be appreciated!
Additional Research...
$scope.treeFamily = { "ID": "1", "type": "Folder", "name": "Harvest", "children": null };
$scope.treeFamily = [{ "ID": "1", "type": "Folder", "name": "Harvest", "children": null }];
This is the difference.....
If i try to do ng-repeat on
$scope.treeFamily = { "ID": "1", "type": "Folder", "name": "Harvest", "children": null };
It will not work because it is expecting an object [...]
$scope.treeFamily = [{ "ID": "1", "type": "Folder", "name": "Harvest", "children": null }];
Thus the above will work.
However, when using the recursive tree, it seems as though it does not EXPECT to see an object other than children... thus
$scope.treeFamily = [{ "ID": "1", "type": "Folder", "name": "Harvest", "children": null }];
will fail......
HOWEVER, I changed my API to return like this:
{ "ID": "1", "type": "Folder", "name": "Harvest", "children": null }
It still wont work!!!!!
This is probably an Angular version issue. Automatic promise unwrapping was removed in version 1.2. Change the code to:
var treeFamily = TreeView.query(function(){
$scope.treeFamily = treeFamily;
});
or use the more explicit promise syntax:
TreeView.query().$promise.then(function(treeFamily){
$scope.treeFamily = treeFamily;
});
I don't think the order matters. Since in the documentation of $resource it says:
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. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most cases one never has to write a callback function for the action methods.
Are you sure data is returned from the server?

Angularjs first attempt at dependency injection

I have a UserAddController and I want to be able to access a list of countries returned by a Web API. The Web API returns data fine. Here is my app.js where I get the data :
app.factory('Country', function ($resource) {
return $resource(
"/api/country/:Id",
{ Id: "#Id" },
{ "update": { method: "PUT" } });
});
This is my Controller :
var UserAddController = function ($scope, $location, service, User) {
$scope.action = "Add";
$scope.countries = service.countries;
};
I am declaring and creating a service here :
app.factory('CountryService', CountryService);
function CountryService($resource) {
return $resource(
"/api/country/:Id",
{ Id: "#Id" },
{ "update": { method: "PUT" } });
}
I am using the same code as above just for testing purposes. I am injecting this service like this :
UserAddController.$inject = ['$scope', 'CountryService'];
This is my first attempt at dependency injection and I cannot figure out where I am going wrong. The error I currently get is 'service is undefined'. I have tried passing both the service and the Country object to the Controller with the same results. Can anybody give any advice?
EDIT : In my Controller, this populates successfully with an alert in the code, but without the alert does not populate. Any reason why this is?
function CountryService($rootScope, $http) {
var self = {};
//self.countries = [{ "$id": "1", "CountryId": 1, "CountryName": "United Kingdom" }, { "$id": "2", "CountryId": 2, "CountryName": "Republic of Ireland" }, { "$id": "3", "CountryId": 3, "CountryName": "Australia" }, { "$id": "4", "CountryId": 4, "CountryName": "New Zealand" }, { "$id": "5", "CountryId": 5, "CountryName": "United States" }, { "$id": "6", "CountryId": 6, "CountryName": "France" }, { "$id": "7", "CountryId": 7, "CountryName": "Germany" }, { "$id": "8", "CountryId": 8, "CountryName": "Finland" }];
$http({
method: 'GET',
url: '/api/country'
}).success(function (data, status, headers, config) {
self.countries = data;
});
alert(self.countries);
return self;
}
You need to add other services/dependencies.
UserAddController.$inject = ['$scope',
'$location',
'CountryService',
'UserService'];
I have assumed that last dependency is a service with name 'UserService'. It's signature would be
app.factory('UserService', UserService);
Edit :
You need to instantiate a new variable.
//Inside function body
$scope.countries = service.countries;
$scope.newCountry = $scope.countries.get({Id : someId},callbackFn);
Now you have a counrtry with 'someId' in $scope.newCountry
Make sure you injected ngResource.
app = angular.module("app", ['ngResource']);
You need to inject the modules correcly
UserAddController.$inject = ['$scope', '$location', 'CountryService', 'user'];
This is quoted the doc.
You can specify the service name by using the $inject property, which
is an array containing strings with names of services to be injected.
The name must match the corresponding service ID registered with
angular. The order of the service IDs matters: the order of the
services in the array will be used when calling the factory function
with injected parameters.
I created a FIDDLE and you can try.

Resources