Angular Resource PUT Operation with Payload - angularjs

I have the following factory to send query to server:
app.factory('Request', ['$resource',
function ($resource) {
var res = $resource("bin/server.fcgi/REST/" + ':resourceName/:ID', {}, {
get : {
method : 'GET'
},
put : {
method : "PUT"
}
});
return {
get : function (arguments, b, c) {
return res.get(arguments, b, c).$promise;
},
put : function(arguments,b,c){
return res.put(arguments, b, c).$promise;
}
};
}
]);
I call it like this:
Request[methodName](params).then(successFunction).catch (failFunction);
However, if i want to send a PUT query:
Request["put"](params).then(successFunction).catch (failFunction);
where
params = {
resourceName : "ATable",
ID : 222,
AProperty : "changedValue"
}
I take then following request: (so an error)
http://myadres.com/REST/ATable/222?AProperty=changedValue
instead of
http://myadres.com/REST/ATable/222
with payload
{ AProperty:changedValue }
What is wrong with this?

app.service('Request', ['$resource',function ($resource) {
var res = $resource('bin/server.fcgi/REST/:resourceName/:ID',
{resourceName: "#resourceName", ID: "#ID"},
{
get : { method : 'GET'},
put : { method : "PUT", params: {resourceName:"#resourceName", ID: "#ID"}//you can leave the string empty if you dont want it to be a defualt value like ID:""
});
this.get = function () {
return res.get().$promise;
}
this.put = function(obj){
return res.put(obj).$promise; // it can be also {like json with your params}
}
]);
and then call it from controller by
var obj = {
ID:222,
resourceName:'ATable'
}
Request.put(obj).then(function(data){
//check whats the data
})
this is how it should be done
maybe not the best way but should work

Related

Ng-file-upload: Sending array to Web Api

Using angularjs 1.3 and C# .net core web api
I have a ng-file-upload which being used to upload file. When the upload method is called I want to pass in an extra array of some data to the upload method which is then received by the method at my web api. Here is my ng-file-upload
factory.upload = function (file, myArray) {
var url = '{0}upload'.format(apiPath)
return Upload.upload({
url: url,
arrayKey: '',
data: { file: file, myArray: myArray}
}).then(function (res) {
return res;
});
};
Below is my webapi:
[HttpPost("upload")]
public async Task<IActionResult> FileUpload(IFormFile file, List<string> myArray)
{
//code
}
And finally here is the array which I am trying to pass along with upload to my webapi:
[
{
id: "1",
name: "steve"
},
{
id: "2",
name: "adam"
}
]
The issue is in my webapi, the myArray parameter which is to accept the array from the UI is always null. I searched online and its mentioned to add
arrayKey: ''
But still doesnt works. Any inputs?
---Updated---
I created a string array as :
var cars = ["steve", "adam", "ronnie"];
And updated my api as:
List<ArrayItem> myArray
The above code works. So looks like there is issue with array being passed.
I am passing the following array by creating like this:
var myArray= [];
for (var i = 0; i < myJson.length; i++) {
myArray.push({
id: myJson[i].id,
name: myJson[i].name,
});
}
The result of above as seen in console:
Array(2)
0:{id: "1", name: "steve"}
1:{id: "2", name: "adam"}
Whats missing here?
For passing object array, you need to define the list object to accept the parameters.
ArrayItem with Id/Name properties.
public class ArrayItem
{
public int Id { get; set; }
public string Name { get; set; }
}
Change action
public async Task<IActionResult> FileUpload(IFormFile file, List<ArrayItem> myArray)
{
return Ok();
}
Update
You need to remove arrayKey: '[]', try code below:
app.service('crudService', function ($http, Upload) {
var baseUrl = 'http://localhost:50829';
this.uploadFile = function (file, array) {
return Upload.upload({
url: baseUrl + "/api/books/file/upload",
//arrayKey: '[]',
data: { file: file, array: array },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function (res) {
return res;
}, function (err) {
throw err;
});
};
});

angular chaining arrays of promises

I am building a website over a database of music tracks. The database is as follows :
music table contains musicid and title
musicrights table contains musicid and memberid
members table contains memberid and memberinfo.
I'm trying to build an array of objects in my database service, which each entry represents a track containing its rightholders (contains information aubout one rightholder but not his name) and their member info (contains name etc). The backend is sailsjs and the code is as follows :
angular.module("myapp").service("database", ["$q", "$http", function($q, $http) {
var database = {};
function getHolderMember(rightHolder) {
return ($http.get("/api/members?where=" + JSON.stringify({
memberid: rightHolder.memberid
})).then(function (res) {
rightHolder.member = res.data[0];
return (rightHolder);
}));
}
function getRightHolders(doc) {
return ($http.get("/api/musicrights?where=" + JSON.stringify({
musicid: doc.musicid
})).then(function(res) {
// array of promises :
// each rightholder of a document has to solve member info
var rightHolders = [];
for (var i in res.data) {
var rightHolder = {
member: res.data[i].memberid,
type: res.data[i].membertype,
rights: res.data[i].memberrights
};
rightHolders.push(getHolderMember(rightHolder));
}
return ($q.all(rightHolders));
}).then(function(rightHolders) {
// expected array of one or two rightholders,
// enriched with member information
// actually returns array of one or two arrays of 30 members
// without rightholder info
console.log(rightHolders);
doc.rightHolders = rightHolders;
return (doc);
}));
}
database.music = function(q) {
return ($http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
}, {
subtitle: {
contains: q
}
}]
})).then(function(res) {
// array of 30 promises :
// each one of 30 documents has to resolve its rightholders
var documents = [];
for (var i in res.data) {
documents.push(getRightHolders(res.data[i]));
}
return ($q.all(documents));
}));
}
return (database);
}]);
The first array of promises seems to work as expected, but not the second one in getRightHolders. What is strange is that this function returns an array of one or two promises, which are rightHolders waiting for their memberinfo. But in the callback where I console.log the response, i get an array of one or two (as per the number of pushed promises) but this array's elements are arrays of 30 memberinfo instead of one memberinfo. I don't understand how this $q.all() call gets mixed with the previous-level $q.all.
The data structure is roughly like this
documents [ ] ($http => 30 responses)
music.musicid
music.rightHolders [ ] ($http => 1, 2, 3 responses)
rightholder.rights
rightholder.member ($http => 1 response)
member.memberinfo
Any help appreciated. Thank you !
UPDATE : Thank you for your answer, it worked like a charm. Here's the updated code, with also the migrate service which formats data differently (there is some database migration going on). I kept it out of the first example but your answer gave me this neat syntax.
angular.module("myApp").service("database", ["$q", "$http", "migrate", function($q, $http, migrate) {
var database = {};
function getHolderMember(rightHolder) {
return ($http.get("/api/members?where=" + JSON.stringify({
memberID: rightHolder.member
})).then(function(res) {
return (migrate.member(res.data[0]));
}).then(function(member) {
rightHolder.member = member;
return (rightHolder);
}));
}
function getRightHolders(doc) {
return ($http.get("/api/rightHolders?where=" + JSON.stringify({
musicID: doc.musicID
})).then(function(res) {
return (
$q.all(res.data
.map(migrate.rightHolder)
.map(getHolderMember)
)
);
}).then(function(rightHolders) {
doc.rightHolders = rightHolders;
return (doc);
}));
}
database.music = function(q) {
return ($http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
},
{
subtitle: {
contains: q
}
}
]
})).then(function(res) {
return (
$q.all(res.data
.map(migrate.music)
.map(getRightHolders)
)
);
}));
}
return (database);
}
I'm not quite sure how you're getting the result you describe, but your logic is more convoluted than it needs to be and I think this might be leading to the issues you're seeing. You're giving the getRightsHolders function the responsibility of returning the document and based on your comment above, it sounds like you previously had the getHolderMember() function doing something similar and then stopped doing that.
We can clean this up by having each function be responsible for the entities it's handling and by using .map() instead of for (please don't use for..in with arrays).
Please give this a try:
angular
.module("myapp")
.service("database", ["$q", "$http", function($q, $http) {
var database = {};
function getHolderMember(memberId) {
var query = JSON.stringify({ memberid: memberid });
return $http.get("/api/members?where=" + query)
.then(function (res) {
return res.data[0];
});
}
function populateRightsHolderWithMember(rightsHolder) {
return getHolderMember(rightsHolder.memberid)
.then(function (member) {
rightsHolder.member = member;
return rightsHolder;
});
}
function getRightHolders(doc) {
var query = JSON.stringify({ musicid: doc.musicid });
return $http.get("/api/musicrights?where=" + query)
.then(function(res) {
return $q.all(res.data.map(populateRightsHolderWithMember));
});
}
function populateDocumentWithRightsHolders(document) {
return getRightsHolders(document)
.then(function(rightsHolders) {
document.rightsHolders = rightsHolders;
return document;
});
}
database.music = function(q) {
return $http.get("/api/music?where=" + JSON.stringify({
or: [{
title: {
contains: q
}
}, {
subtitle: {
contains: q
}
}]
})).then(function(res) {
return $q.all(res.data.map(populateDocumentWithRightsHolders));
});
}
return (database);
}]);

MEAN & Geospatial queries - Find LineStrings Intersecting on Another One given Its Name

I'm trying to build an application using MEAN but now I'm stuck when trying to find linestrings intersecting on another one given its name.
For instance, given the following image, poly1 and poly2 should have intersections while poly3 does not.
Let's suppose poly1 has the following coordinates and the following JSON:
{
"_id" : ObjectId("57ab2107505ab11b1bd8422e"),
"name" : "poly1",
"updated_at" : ISODate("2016-08-10T12:41:43.789+0000"),
"created_at" : ISODate("2016-08-10T12:41:43.780+0000"),
"geo" : {
"coordinates" : [ [14.59, 24.847], [28.477, 15.961] ],
"type" : "LineString"
},
"__v" : NumberInt(0)
}
When I run the query on MongoChef I find both poly1 and poly2 and I do not find poly3 like I want:
{
geo :{
$geoIntersects:{
$geometry :{
type: "LineString" ,
coordinates: [ [14.59, 24.847], [28.477, 15.961] ]
}
}
}
}
While, when I run the query on Mongoose given a Polyline Id/name it does not work
//Given
var linestringById = Linestrings.find({name : lineName});
var linestrings = Linestrings.find({});
//Works
query = linestrings.where({ geo : { $geoIntersects :
{ $geometry :
{ type : 'LineString',
coordinates : [ [27.528, 25.006], [14.063, 15.591] ]
}
} } });
//Does not work
query = linestrings.where({ geo : { $geoIntersects :
{ $geometry :
{ type : 'LineString',
coordinates : linestringById.geo.coordinates
}
} } });
//Also does not work:
query = linestrings.where({ geo : { $geoIntersects :
{ $geometry :
{ type : 'LineString',
coordinates : linestringById
}
} } });
This is the Schema for LineStrings:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// Creates a LineString Schema.
var linestrings = new Schema({
name: {type: String, required : true},
geo : {
type : {type: String, default: "LineString"},
coordinates : Array
},
created_at: {type: Date, default: Date.now},
updated_at: {type: Date, default: Date.now}
});
// Sets the created_at parameter equal to the current time
linestrings.pre('save', function(next){
now = new Date();
this.updated_at = now;
if(!this.created_at) {
this.created_at = now
}
next();
});
linestrings.index({geo : '2dsphere'});
module.exports = mongoose.model('linestrings', linestrings);
This is how I call the query from the front-end QueryController.js
/** Looks for LineStrings intersecting a given linestring **/
vm.polyIntersect = function () {
//Taking name from a form
vm.queryBody = {
name : vm.formData.poly1
};
// Post the queryBody
$http.post('/find-poly-intersection', vm.queryBody)
.success(function(queryResults) {
console.log(queryResults);
})
.error(function(queryResults) {
console.log('Error: no results found '+queryResults));
});
};
This is my Route.js:
/** Requiring Factories **/
var LinestringFactory = require('./factories/linestring.factory.js');
module.exports = function(app) {
// Retrieves JSON records for all linestrings intersecting a given one
app.post('/find-poly-intersection', function(req, res) {
LinestringFactory.findIntersections(req).then( function (linestrings) {
return res.json(linestrings);
}, function (error) {
return res.json(error);
})
});
}
This is my LineString.factory.js:
var Linestrings = require('../models/linestring-model.js');
exports.findIntersections = findIntersections;
/** Finds Linestrings Intersections **/
function findIntersections(req) {
return new Promise( function (resolve, reject) {
var lineName = req.body.name;
var linestringById = Linestrings.find({name : lineName});
var linestrings = Linestrings.find({});
//Check if that certain linestring exists with Lodash
if (_.isEmpty(linestringById) || _.isUndefined(linestringById)
|| _.isNull(linestringById)){
return reject('No Linestrings found for that Name');
} else {
query = linestrings.where({ geo :
{ $geoIntersects : { $geometry :
{ type : 'LineString',
coordinates : linestringById.geo.coordinates}
} } });
query.exec(function (err, intersections) {
if (err){
return reject(err);
}
return resolve(intersections);
});
}, function (error) {
return reject(error);
})
}
console.log in QueryController gives me always Object {} for any
linestring name.
This is the Mongoose Log of the query.
I'm making sure of inserting [lng, lat] coordinates
Have you any idea on why I can't find any LineString intersecting by Id while I can find them using straight coordinates?
Thanks in advance.
You are passing linestring.geo.coordinates in latitute,longitute format to the final query.
Mongodb accepts coordinates in the x,y format, hence it has to be longitude,latitude
Updated:
You will need to directly pass the linestring as $geometry.
query = linestrings.where({ geo : { $geoIntersects :
{
$geometry : lineStringbyId.
} } });
I finally managed to solve this issue with the following code
/** Finds Linestrings Intersections **/
function findIntersections(req) {
return new Promise( function (resolve, reject) {
var lineName = req.body.name;
Linestrings.findOne({name : lineName}).then( function (linestringById, error) {
if(error){
return reject({error : 'LineString not Found'});
}
queryIntersections(linestringById).then( function (response) {
return resolve(response);
});
});
}, function (error) {
return reject({error : 'Error while executing promise'});
});
}
function queryIntersections(linestringById) {
return new Promise( function (resolve, reject) {
if (_.isEmpty(linestringById) || _.isUndefined(linestringById) || _.isNull(linestringById)){
return reject({ error : 'No Linestrings found for that Name'});
} else {
query = Linestrings.where( { geo : { $geoIntersects : { $geometry : { type: 'LineString', coordinates: linestringById.geo.coordinates } } } } );
queryExec(query).then( function (intersections) {
return resolve(intersections);
});
}
}, function (error){
return reject({error : 'Error while executing promise'});
});
}
The error was caused by the fact that I did not pass correctly linestrings and linestringById objects to the query.
I hope it will help someone.

Multiple select2 angularUI load remote data

I have an issue with loading remote data in multiple select2. My code is
var fetchGroups = function (queryParams) {
console.log(JSON.stringify(queryParams));
return $http.get("https://******/****/***/" + queryParams.data.query).then(queryParams.success);
};
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
quietMillis: 500,
transport: fetchGroups,
results: function (data, page) {
console.log(data);
// parse the results into the format expected by Select2 return { results: data };
var drastics = data.data.result;
if(drastics){
var data = new Array();
for(var i = 0; i < drastics.length; i++){
data.push(
{
id: drastics[i].id,
text: drastics[i].name
}
);
}
} else {
data = data.data.result;
}
return { results: data };
}
}
};
It returns the values from the get request but when i select it returns undefined at the input box.
Just make sure you've included the 'data' property to the $scope.groupSelectOptions like so :
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
.....
data:[]}
You should now see the term selected in the input field.

how to check the return status of the store 's sync In Extjs

I use the the
store.sync({
success:function(){},
failure:function(){}
});
to sync with the server; when the server return {success:false} or {success:true};
how I check the json from the server in the store.sync.
I have knew that:success is called by The function to be called upon successful completion of the sync ,even if return {sucess :false} ,not only the {success:true};
You need to change the reader's successProperty to false in the store's proxy.
store.proxy.reader.successProperty = false;
or
var store = Ext.create('Ext.data.Store', {
(...)
proxy : {
type : 'ajax',
(...)
reader : {
successProperty : false,
(...)
}
}
});
and then you can use this:
store.sync({
callback : function (batch, options) {
var operations = batch.operations;
for (var x in operations) {
var operation = operations[x];
if (operation.request) {
console.log('operation.request ---> ', operation.request);
}
if (operation.response) {
console.log('operation.response ---> ', operation.response);
var object = Ext.decode(operation.response.responseText, false);
console.log('success --->', object.success);
}
}
}
});

Resources