AngularJS: ngResource and array of object as params to URL - angularjs

I have variable $scope.data= [{column:"age", operator: ">", value: "50"}, {column:"name", operator: "=", value: "Tonda"}]. And service for submitting data to server:
angular.module('myServices', ['ngResource']).
factory('serverApp', function($resource, $scope){
return $resource('myurl/', {}, {
saveData: {method:'POST', params: $scope.data}
});
});
Why URL contains "nonsense" after calling `serverApp.saveData()? - .../myurl?0=%5Bobject+Object%5D&1=%5Bobject+Object%5D - It seems, that params can be only simple (1D) object.
How can I properly serialize object $scope.cfgcondition into params of service serverApp (eg. to URL)? Thanks.

The 'params' attribute defines URL query params, which I assume is intended behavior. If it was just a simple object, not an array, then you could just use $save something like
var MyRequest = $resource('/notreally');
$scope.data = new MyRequest;
// get stuff into $scope.data
$scope.doSubmit = function() { $scope.data.$save(); }
To post an array you need to define your own action and pass the data in as second parameter.
$scope.data= [{column:"age", operator: ">", value: "50"},
{column:"name", operator: "=", value: "Tonda"}];
var MyRequest = $resource('/notreally', {}, {saveData: {method:'POST', isArray: true}});
$scope.doSubmit = function() { MyRequest.saveData({}, $scope.data);
http://docs.angularjs.org/api/ngResource.$resource
https://docs.angularjs.org/api/ngResource/service/$resource
*Edited to fix misstatements regarding arrays - I thought $resource could not POST arrays, but figured out that I was wrong!

Related

Mongoose and Angular Populate Issue

I am new to mongoose and Angular and I am having an issue with mongoose's populate method. I have the following two mongoose schemas
var JobSchema = new mongoose.Schema({
jobName: String,
jobType: String,
status: String,
examples: [{type: mongoose.Schema.Types.ObjectId, ref: 'Example'}]
});
mongoose.model('Job', JobSchema);
and
var ExampleSchema = new mongoose.Schema({
content: String,
job: {type: mongoose.Schema.Types.ObjectId, ref: 'Job'}
});
mongoose.model('Example', ExampleSchema);
So basically the Job schema contains Example's. I also have the following Express route for getting the examples from a particular Job. I used this tutorial to figure out how to do this.
var Job = mongoose.model('Job');
var Example = mongoose.model('Example');
router.get('/jobs/:job', function (req, res) {
req.job.populate('examples', function (err, job) {
if (err) {return next(err);}
res.json(job);
});
});
Also, I am using the following to automatically retrieve the job from mongo and attach it to req.
router.param('job', function (req, res, next, id) {
var query = Job.findById(id);
query.exec(function (err, job) {
if (err) {
return next(err);
}
if (!job) {
return next(new Error('can\'t find job'));
}
req.job = job;
return next();
});
});
I also have the following Angular factory that uses this route
app.factory('jobs', ['$http', function ($http) {
var o = {
jobs: []
};
o.get = function (id) {
return $http.get('/jobs/' + id).then(function (res) {
return res.data;
});
};
return o;
}]);
I also created the following state which is supposed to immediately populate the examples for a given Job id using the above factory.
.state('jobs', {
url: '/jobs/{id}',
templateUrl: '/jobs.html',
controller: 'NerCtrl',
resolve: {
post: ['$stateParams', 'jobs', function ($stateParams, jobs) {
return jobs.get($stateParams.id);
}]
}
});
The problem comes when I actually try to show the examples using a controller.
app.controller('NerCtrl', [
'$scope',
'job',
function ($scope, job) {
$scope.examples = job.examples;
}]);
The view that tries to use $scope.examples just displays {{examples}} rather than the actual content of the scope variable. In fact, nothing in the controller seems to work with the `job` injection (not even simple 'alerts').
It looks the problem comes from the `job` injection in the controller. This is supposed to refer to the job that is retrieved in the resolve given the id but it doesn't look like this is working.
In addition, I have curled an example record's url (eg. curl http://localhost:3000/jobs/56920a1329cda48f16fc0815) and it does return the desired Job record, so it does look like the route part is working correctly. I suspect the problem is somewhere in the 'resolve' or the way in which I am injecting the result of the resolve into the controller.
Ok this was a silly mistake. The post inside the Job state should have been job. i.e.
.state('jobs', {
url: '/jobs/{id}',
templateUrl: '/jobs.html',
controller: 'NerCtrl',
resolve: {
job: ['$stateParams', 'jobs', function ($stateParams, jobs) {
return jobs.get($stateParams.id);
}]
}
});
In my inexperience, I did not know what post was referring to, but I suppose it refers to the job that is returned from jobs.get($stateParams.id) which is then the name that gets injected in the controller. So obviously the name in resolve must be consistent with what is injected in the controller.

ui-route update url without param

i'm trying to update url without params is it possible ? on my app i created state
.state('webPrint', {
url: '/web/print/:lead',
templateUrl: '/application/views/web-print.html'
})
and when i'm redirecting i'm passing an object
var obj = JSON.stringify(lead);
$state.go('webPrint', { lead: obj });
but my url is something should be like
/web to /web/print but it shows /web/print + "stringify object data" so i changed my code to
$state.go('webPrint', { lead: obj }, { location: false, inherit: false });
but now it's not change url at all. i mean /web to /web
how can i avoid stringify string on url and pass direct to new url?
thanks
You are using option location: false which means you are telling not to change the url.
I would say create a service with getter and setter to save and retrieve your data like below
angular.module('app.service').factory('leadService', function(){
var lead = {};
return{
getLead : function(){
return lead;
},
setLead: function(data){
lead = data;
}
}
});
.state('webPrint', {
url: '/web/print',
templateUrl: '/application/views/web-print.html'
})
var obj = JSON.stringify(lead);
leadService.setLead(obj);
$state.go('webPrint');
Then in your controller get the lead Object using
var lead = leadService.getLead();

Angular JS - Manipulating Data in a Service / Factory and Making Sanitized Object Available to Controller

I currently have a simple factory like the following:
myFactory.factory('myFactory', function($resource){
return $resource('http://to/my/api', {}, {
query: {
method: 'GET'
}
});
});
I would like to move some of the data manipulation / sanitation that I am currently doing in my controller to my factory. I changed my factory to the following:
myFactory.factory('myFactory', function($resource){
var connection = $resource('http://to/my/api', {}, {
query: {
method: 'GET'
}
});
var filters = connection.query();
for(var i = 0; i < filters.data.length; i++){
// Get the name value in the data array
var name = filters.data[i].Name;
// Create new properties in $scope.filters and assign arrays to them. Each array is a separate filter
filters[name] = filters.data[i].Values;
}
return filters;
});
Essentially what I am doing in the above is reordering the structure of the object array returned from the AJAX call.
When I try to console log my 'filters' variable from the factory in my controller, I get an 'undefined' message. What is wrong with my above factory syntax?
Because you're not publicly exposing anything to return filters, try:
myFactory.factory('myFactory', function($resource){
return {
getFilters:function(){
var connection = $resource('http://to/my/api', {}, {
query: {
method: 'GET'
}
});
var filters = connection.query();
for(var i = 0; i < filters.data.length; i++){
// Get the name value in the data array
var name = filters.data[i].Name;
// Create new properties in $scope.filters and assign arrays to them. Each array is a separate filter
filters[name] = filters.data[i].Values;
}
return filters;
}
}
});
and call it like this in your controller:
$scope.filters = myFactory.getFilters();
Excuse the horrible formatting, here's a plunk.

AngularJs change location after save

I'm having trouble changing location after I save a new customer in an angular.
Here's my controller.
function CustomersNewController($scope, $location, Customer) {
$scope.selected_customer = '';
$scope.submit = function() {
rails_customer = new Customer({customer: $scope.new_customer});
rails_customer.$save({format: 'json'},function(data, getResponseHeaders) {
$location.path(data.id + '/edit/') ;
}, function(data, getResponseHeaders) {
console.log("ERROR");
});
};
}
The customer saves to the database fine. The problem is that I can't get the id of the object that was just saved in order to redirect to the edit page.
The 'data' object is populated but it looks like this:
b {customer: Object, $then: function, $resolved: true, $get: function, $save: function…}
$resolved: true
$then: function (callback, errback) {
customer: Object
Can anyone give me a hand on how to dig the id out of the returned data?
Thanks!
According to your data object it should be
$location.path(data.customer.id + '/edit');

Laravel 4 and Backbone not playing well together -- JSON improperly formatted

I'm trying to return JSON output from a Laravel route. Here's my route:
Route::get('main-contact-count', function() {
$mc = MainContact::where('flag', '=', '1')->count();
return Response::json(['count' => $mc]);
});
If I look at the response tab in Firebug, I'm getting back:
{"count":9}
The JSON encoding is missing the square brackets. This JSON is different than the JSON Laravel returns from a resourceful controller. It has the square brackets. Backbone parses it fine. Backbone doesn't parse the above JSON correctly. If you look at the length and models when you console.log a collection, they're both zero. You can, however, drill down into the object and you can find a count property set to 9.
How do I get the correct JSON out of Laravel?
Just for kicks and giggles, I'm posting my Backbone, in case I'm doing something hinky there:
App.Collections.Count = Backbone.Collection.extend({
model: App.Models.Count,
initialize: function(models, options) {
this.fetch({
success: function(data, options) {
// console.log(data.models);
}
});
if (options) {
this.url = this.url || options.url;
}
}
});
App.Views.Count = Backbone.View.extend({
tagName: 'span',
className: 'leadCount',
template: _.template($('#contactCount').html()),
initialize: function() {
},
render: function() {
this.$el.html(this.template(this.collection.toJSON()));
return this;
}
});
And in my route:
var mc = new (App.Collections.Count.extend({ url: 'main-contact-count' }))();
var mcv = new (App.Views.Count.extend({ collection: mc }))();
The JSON response sent by your service is a single JSON object ({...}) Your collection is not able to parse it because it expects an array of JSON objects ([{...}, {...}]).
If I've understood your code correctly, /main-contact-count is a specialized service whose function is to return and single datum: a count of contacts. If this is the case, Backbone.Collection may not be the correct solution. Collections are meant for... well, collections of things.
You should use just a model instead:
App.Models.Count = Backbone.Model.extend({
url:'main-contact-count'
});
var countModel = new App.Models.Count();
countModel.fetch({success: function(model, resp) {
var count = model.get('count');
});
Or even better, forego Backbone altogether and just fetch the data using jQuery:
$.getJSON('main-contact-count', function(response) {
var count = response.count;
});
try:
return Response::json(array(array('count' => $mc));

Resources