AngularJS reload data after PUT request - angularjs

Should be a fairly easy one here for anyone who knows Angular. I am trying to update the data that is displayed after I make a PUT request to update the object. Here is some code:
Post service (services/post.js)
'use strict';
angular.module('hackaboxApp')
.factory('Post', function($resource) {
return $resource('/api/posts/:id', {id : '#id'}, {
'update': { method: 'PUT' }
})
});
Server side controller function that gets executed when trying to update data (lib/controllers/api.js)
exports.editsave = function(req, res, next) {
var posty = req.body;
console.log(posty._id.toString() + " this is posty");
function callback (err, numAffected) {
console.log(err + " " + numAffected);
if(!err) {
res.send(200);
//res.redirect('/forum');
}
}
Post.update(posty, { id: posty._id.toString() }, callback);
};
This is the console output for the above code:
53c54a0d4960ddc11495d7d7 this is posty
null 0
So as you can see, it isn't affecting any of the MongoDB documents, but it also isn't producing errors.
This is what happens on the client (Angular) side when a post is updated:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
// Now call update passing in the ID first then the object you are updating
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
After the redirect, $location.path('/forum'), none of the data is displayed as being updated...when I look in the database...nothing has changed either...it is like I am missing the step to save the changes...but I thought that update (a PUT request) would do that for me.
I use ng-init="loadposts()" when the /forum route is loaded:
$scope.loadposts = function() {
$http.get('/api/posts').success(function (data) {$scope.posts = data});
};
Shouldn't all the new data be loaded after this? Any help would be appreciated. Thanks!

Your server side output indicate that the update query doesn't match any document in the database.
I'm guessing that you are using Mongoose in NodeJS server side code to connect to mongodb.
If that the case, your update statement seems incorrect.
Instead of { id: .. } it should be { _id: .. }
Also the conditions object and updated object are swapped.
The statement should be like this:
Post.update({ _id: posty._id.toString() }, posty, callback);
If you are not using Mongoose, please eloborate more on which library you are using or better than that, show the code where the Post variable is defined in your server side code.

Ok I got it.
the problem is that you are not using the Angular resource api correct.
This code need to be changed:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
Into:
// Update existing Post
$scope.saveedit = function() {
var editedpost = new Post($scope.post); //New post object
editedpost.$update(function() {
$location.path('/forum');
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
And as for the server code (taken from my own working module):
exports.update = function (req, res) {
var post == req.post;
post = _.extend(post, req.body);
post.save(function (err) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(post);
}
});
};

Related

ngTable with data from web api not working

I'm using ngTable for AngularJS and geting the data from a web api. The problem start when I tried to use the filters in the table.
If I do it this way, the table is filled with the data, but the filters don't works:
$scope.clientesTable = new NgTableParams({
page: 1,
count: 10
}, {
getData: function (params) {
var clientes = clientesService.getAll(baseUrl);
clientes.then(function (data) {
$scope.clientesTableData = data.data;
}, function (error) {
console.log("Error: " + error);
});
}
});
In the documentation the code is something like this:
$scope.clientesTable = new NgTableParams({
page: 1,
count: 10
}, {
getData: function (params) {
var clientes = clientesService.getAll(baseUrl);
clientes.then(function (data) {
params.total(data.inlineCount);
return data.results;
}, function (error) {
console.log("Error: " + error);
});
}
});
Doing it this way, I don't see the data in the frontend. If a look for data in clientesTable:
EDIT:
Response from web api:
You have to provide return keyword before clientes.then() inside getData method.
If I look at this answer https://stackoverflow.com/a/29629034/3177115 I see that NgTableParams is used differently. You need to use it with a promise which returns the data back into the NgTableParams object.
$scope.tableParams = new ngTableParams({
page: 1, count: 5,
}, {
getData: function ($defer, params) {
$http.get(testUrl, { params: params })
.then(function(res) {
$defer.resolve(res.data.items);
}, function(reason) {
$defer.reject();
}
);
},
});
Please see the full example for details, I have simplified the example a bit for better understanding.
EDIT:
I think the API of ng-tables has changed - it does not expect a deferer any more.
Looking now at your first code example again (which you say it works) I see why the filter is not working: You do not pass the filter information back to your service.
The ng-table docs say: http://ng-table.com/#/filtering/demo-filtering-basic
Got a getData function? In this case you'll need to apply the values
from NgTableParams.filters() to the data you want to display in your
table. This is typically the case when the data is being fetched from
the server
I don't know your service, but can you add the filter params to the service call?
var clientes = clientesService.getAll(baseUrl, params._params)
Btw: the docs of ng-table are a nightmare - all samples inherit from each other and use directives and injects.

How to post data on button click using AngularJS

I have an application made with .NET core framework and pure html in the front end. I was using AJAX to post and get data.
I am new to Angular and decided to convert the front end of the application to Angular for learning purposes.
For Example, I have a button that will change the state of employees from 'Billed' to 'Available' state. The ID for available state is defined in the back end and it is '1'.
//MOVE TO BENCH BUTTON CLICK
$(document).ready(function()
{
var allVals = [];
$("#MoveToBench").click(function()
{
$('input:checkbox:checked').each(function () {
allVals.push($(this).val());
});
for (i = 0;i<allVals.length;i++){
PostBenchList(allVals[i])
}
function PostBenchList(entityId) {
var data = 'entityID='.concat(entityId).concat('&nextStateId=1');
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "http://localhost:1783/api/Workflow?"+data,
data: data,
dataType: "text",
success: function (data) {
location.reload();
alert("Successfully added the selected Employees to TalentPool");
},
fail: function (error) {
Console.Log(error);
}
})
}
});
});
The above code is taking an array of entityID's as input. For the Angular application, the array is not required as only one entity ID will be passed.
The API controller in the backend is :
// POST api/values
[HttpPost]
public void Post(int entityId, int nextStateId)
{
JObject jsonObject = JObject.Parse(System.IO.File.ReadAllText("Config.Json"));
string jsonFile = jsonObject.GetValue("WorkfowJsonFileLocation").ToString();
var nextState = _stateServices.Get(nextStateId);
var handler = new WorkflowHandler(nextState, jsonFile, _entityServices, 1, _stateServices, _subStateServices, _appServices);
handler.PerformAction(entityId);
}
The above code worked for me and it would change the state ID of the employee(EntityID)to 1(nextStateId)
Now I have a button in AngularJS and I want it to do the same action. How would I achieve this? As I am still in the procedure of learning, I don't have a clue how to do this. Can anyone help me to achieve this? This would help me to learn and do all similar buttons.
Thank You.
You can use ng-click and call a function to post the data,
HTML:
<button ng-click="PostData()">
Click to POST
</button>
Controller:
app.controller('PostController',['$scope',function($scope)
{
$scope.sendPost = function() {
var data = $.param({
json: JSON.stringify({
name: $scope.newName
})
});
$http.post("/echo/json/", data).success(function(data, status) {
$scope.hello = data;
})
}
}]);
DEMO APP

Ionic Framework Using Phonegap Facebook Connect Plugin API cant make pagination of friends work

My ionic view uses infinite scroll for friends view and here is the controller:
$scope.friends = [];
$scope.after = "";
var getFriends = function(after)
{
var friends = $q.defer();
UserService.getUser().then(function (d) {
var url = '/me?fields=taggable_friends&access_token='+ d.authResponse.accessToken;
if (after != "")
{
url += "&limit=25&after="+after;
}
facebookConnectPlugin.api(url, null,
function (response) {
console.log(response);
friends.resolve(response);
},
function (response) {
console.log(response);
friends.reject(response);
}
);
});
return friends.promise;
};
$scope.loadMoreData = function()
{
getFriends($scope.after).then(function(d)
{
$scope.friends = $scope.friends.concat(d.taggable_friends.data);
$scope.after = d.taggable_friends.paging.cursors.after;
$scope.$broadcast('scroll.infiniteScrollComplete');
});
};
The first call is executed to url:
"/me?fields=taggable_friends&access_token=myAccessToken" and I receive an object as follows:
object
{
id: "string"
taggable_friends
{
data
{
[n]objects
}
paging
{
cursors
{
after: "string"
before: "string"
}
next: "string"
}
}
}
The second call url is:
/me?fields=taggable_friends&access_token=myAccessToken&after=QWFKVko1NlJmWUREajBTeERZAbmFJUzlLUWp5ZA3o5cDA5SWVHc1BKblJ6ODMweDd4TzdxMlJyOTdKNDlUb0NHQWl1M3FJbXdjbkpWc2NwSlNiS25peV8zYV9vdTdGbXFPMG5YNnpDSW1jWkVNX0EZD
In both cases I get the same object. With exactly the same Data. When I use browser for the 2 URLs, i get different (correct) data.
I even tried to request /me?fields=taggable_friends&access_token=myAccessToken&after=QWFKVko1NlJmWUREajBTeERZAbmFJUzlLUWp5ZA3o5cDA5SWVHc1BKblJ6ODMweDd4TzdxMlJyOTdKNDlUb0NHQWl1M3FJbXdjbkpWc2NwSlNiS25peV8zYV9vdTdGbXFPMG5YNnpDSW1jWkVNX0EZD in first call, but still I get the same data.
Finally i found the solution!
I don't know what the reason is, but API call like "/me?fields=taggable_friends&access_token=..." don't work when "after" parameter is added.
It should be used this way: "/me/taggable_friends?access_token=...", this way it works.

PUT request not working in Node.js

I am trying to update an existing document in mongodb with node.js. But it does not seem to work. It do not even display the request call in the console. Please suggest what mistake I am doing or how I can I do the update operation in node.js with mongodb. Here is the code:
Node.js Code:
app.put('/addIssueId', function(req, res) {
console.log("Adding issue id")
console.log(req.body.issueKey)
impactMapFeature.update( {productName:req.params.productName, actor:req.body.actor, activity:req.body.activity,feature:req.body.feature},{issueKey:req.body.issueKey}, function ( err, data ) {
console.log("Updating" + data)
});
});
Angular Controller code:
var data = {
productName: $scope.productName,
actor: actor,
activity: impact,
feature : $('#feature').val(),
issueKey : data.key
};
$http.put('/addIssueId', data)
.success(function(data){
}).error(function(data){
console.log('Error in adding issueId' + data)
});
}
As chridam said, you are using req.params which is a route parameter. Either use the following route : /addIssueId/:productName or pass your variable with a query parameter : /addIssueId?productName=productName and {productName = req.query.productName, ... }, or pass your variable as you are doing it in the body (then you just need to change req.params.productName to req.body.productName

request timeout in node application

The request I make to my node api takes more than 4 minutes to respond. While the time the response is received. The angular app does not accept the response. On firebug, the url turns red.
How can I overcome this.
api.route('/allsearch')
.post(function(req,res){
var filters=req.body.everything;
var filterid=req.body.filterId;
var searchid=req.body.searchid;
var zipgroup=req.body.zipgroup;
var myObject = new Array();
function getData(docs, filters, filterid, callback) {
function loop(i) {
searchingalgo(docs[i], filters, filterid, function(pers){
myObject[i] = pers;
if (i < docs.length) {
loop(i + 1);
} else {
callback();
}
});
};
loop(0);
};//closing get data()
Searchradius.findOne({"searchid" : searchid, user: req.decoded.id}).exec(function(err, docs) {
// Array to hold async tasks
var asyncTasks = [];
// Loop through some items
zipgroup.forEach(function(item){
// We don't actually execute the async action here
// We add a function containing it to an array of "tasks"
asyncTasks.push(function(callback){
// Call an async function, often a save() to DB
console.log(item);
searchingalgo(item, filters, filterid, function(pers){
myObject[item] = pers;
// Async call is done, alert via callback
callback();
});
});
});
Async.parallel(asyncTasks, function(){
//console.log(myObject);
Searchradius.update({ _id: searchid }, { $set: { ucounteds: myObject , uzips: zipgroup }}, function(err, result){
if(err) {
res.send(err);
return;
}
var fields = ['city', 'state', 'zip','distance', 'count'];
var myresults = [];
var tc=0;
var newMyobj= new Array();
co=0;
zipgroup.forEach(function(item){
tc+=myObject[item];
//myresults.push(jobj);
});
for(i=0;i<zipgroup.length;i++){
newMyobj[i]=myObject[zipgroup[i]];
}
console.log(tc);
Searchfilter.update({ _id: filterid }, { $set: { counted_results: tc }}, function(err, resultupdate){
//console.log(resultupdate);
//console.log(tc);
});
// console.log(myObject);
// console.log(newMyobj);
res.json({
success: true,
zips: zipgroup,
states: docs.states,
cities: docs.cities,
distances: docs.distances,
counted_results : newMyobj,
});
}); //update searchradius
}); //getdata function
}); //searchradius findone
});
As requested, this is my node API. the zipgroup is a array of zips like
[37663, 37664, 37669, 37671, 37660, 37669, 37667, 37668, 37666, 37665, 37662, 37661]
Just to be clear the collection Consumer1s has more than 2900009876 documents. It is indexed properly and the query is taking the least time possible. But I am still facing this problem.
Any suggestions would be helpful.
This is my post request from angular controller.
$http.post('/api/allsearch',
{
"everything":$scope.filterSearch ,
"searchid":$routeParams.id,
"filterId": $scope.filterId,
"zipgroup" : $scope.zipgroup
})
.success(function(data){
for(var i=0; i<data.zips.length;i++){
oneset={
"zip": data.zips[i],
"state": data.states[i],
"city": data.cities[i],
"distance": data.distances[i],
"count": data.counted_results[i]
};
$scope.totalCount+=data.counted_results[i];
$scope.results.push(oneset);
}
angular.forEach($scope.results, function (result) {
result.distance = parseFloat(result.distance);
});
$rootScope.processing=false;
$scope.filterlinkdisplay=true;
});
There are at least several options:
set AngularJS $http timeout for 10 mins or so, so that AngularJS request doesn't time out, waiting for 4 mins to get the data
polling: 1) AngularJS app does initial request 2) Node.js server issues a unique token to AngularJS app for this request and starts working on collecting data 3) AngularJS app waits for several mins and does a request with previously received token to get data 4) If result is ready, you're done. If not, wait again and do another request from AngularJS
use WebSocket. On client side it is supported by many browsers, on server side use ws. It's a bi-directional protocol, so server can notify clients when data is ready.

Resources