Sails.js error issue while deleting any record - javascript

I am new in sails js , Here i am follow one tutorial to create crud using sails js and mongodb.
But while deleting any record getting 500 internal server error
console error
"NetworkError: 500 Internal Server Error - http://localhost:1337/user/delete/55bf315ee3437a512628916b"
Here is my controller file delete function:
delete: function(req, res) {
var id=req.param("id",null);
User.findOne(id).done(function(err, user) {
// we now have a model with instance methods attached
// destroy the record
user.destroy(function(err) {
res.redirect( 'user/index/');
// record has been removed
});
});
}
Here is my view
+Create
<ol>
<% users.forEach( function( model ){ %>
<li><%= model.name %>(delete||Update||view)</li>
<% }); %>
</ol>
// Here is my route file
module.exports.routes = {
'/': {
view: 'homepage'
},
'post/User':{
view: 'user/create'
}
};
Please guide me i dont't know where i am doing mistake.
Thanks in advance

I think the mistake could be in the res.redirect,
you should place it outside destroy() function.
delete: function(req, res) {
var id=req.param("id",null);
User.findOne(id).done(function(err, user) {
// we now have a model with instance methods attached
// destroy the record
user.destroy(function(err) {
if (err) return
});
res.redirect( 'user/index/');
});
}

I was fixed the error , its come since i am using
User.findOne(id).done(function(err, user) {
..
}
Insted of this :
User.findOne(id).exec(function(err, user) {
.. ^^^^^^
}

Related

Hook in meteor to catch all collection method errors

I have a collections for Errors that displays to the user. I want to insert into this collection whenever a user receives an error, so it can be displayed in a template.
I have a few hooks on my collections that will reject it.
// only admins can create and update plans
Plans.allow({
insert: function(userId, doc) {
return Roles.userIsInRoles(userId, 'admin');
},
update: function(userId, doc) {
return Roles.userIsInRoles(userId, 'admin');
}
});
// Can only have one active plan currently
Plans.deny({
update: function(userId, doc) {
var now = new Date();
Plans.find({
active: true,
_id: { $in: doc.planIds },
dateStart: { $gt: now },
dateEnd: { $lt: now }
}).count() > 0;
}
});
My question is; can I listen to these events and, when rejected, take a particular action on the client and server?
You can insert on the collection via the callback function on whatever insert/update/remove you have.
If you want to do to on the server way (sing Meteor.methdos/Meteor.call), this is the workflow.
JS
//server
Meteor.method({
insertDoc:function(doc){
Plans.insert(doc)
}
})
//Client
Errors = new Mongo.Collection(null) //client side only
Meteor.call('insertDoc',{test:doc},function(err,result){
if(err){
Error.insert({error:err.reason}) //if there is a error lets insert it
}
})
//and the helper to show the error.
Template.example.helpers({
showError:function(){
return Error.find();
}
})
HTML
<template name="example">
<span>Sorry there was an error: {{error}}</span>
</template>
You got the idea.

Track and count clicks with AngularJS and post to MongoDB

I want to be able to track the click from a user on an item and have it update the JSON object associate with it and display the number of all the clicks. I know how to create and delete an object, but how do I add a new name and value and update the object when the user clicks and appropriate vote button? Any help will be greatly appreciated and I thank you in advance.
The HTML
<body ng-controller="mainController">
<div class="table-responsive">
<table class="table">
<tr>
<td>Vote</td>
<td>Song</td>
<td>Edit</td>
</tr>
<tr ng-repeat="todo in todos">
<td><button class="btn btn-success icon-thumbs-up" alt="Up vote this song if you like it.">Vote</button></td>
<td>{{ todo.text }}</td>
<td><button class="btn btn-danger fa fa-times" ng-click="deleteTodo(todo._id)" alt="Remove the song if you need to make an edit and then add it back."></button></td>
</tr>
</table>
</div>
</body>
The Model
var mongoose = require('mongoose');
module.exports = mongoose.model('Todo', {
text : String,
done : Boolean
});
The Service
angular.module('todoService', [])
// super simple service
// each function returns a promise object
.factory('Todos', function($http) {
return {
get : function() {
return $http.get('/api/todos');
},
create : function(todoData) {
return $http.post('/api/todos', todoData);
},
delete : function(id) {
return $http.delete('/api/todos/' + id);
}
}
});
Server side Angular
var Todo = require('./models/todo');
module.exports = function(app) {
// api ---------------------------------------------------------------------
// get all todos
app.get('/api/todos', function(req, res) {
// use mongoose to get all todos in the database
Todo.find(function(err, todos) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
res.json(todos); // return all todos in JSON format
});
});
// create todo and send back all todos after creation
app.post('/api/todos', function(req, res) {
// create a todo, information comes from AJAX request from Angular
Todo.create({
text : req.body.text,
done : false
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// delete a todo
app.delete('/api/todos/:todo_id', function(req, res) {
Todo.remove({
_id : req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// application -------------------------------------------------------------
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
};
Client side Angular
angular.module('todoController', [])
// inject the Todo service factory into our controller
.controller('mainController', function($scope, $http, Todos) {
$scope.formData = {};
$scope.loading = true;
// GET =====================================================================
// when landing on the page, get all todos and show them
// use the service to get all the todos
Todos.get()
.success(function(data) {
$scope.todos = data;
$scope.loading = false;
});
// CREATE ==================================================================
// when submitting the add form, send the text to the node API
$scope.createTodo = function() {
$scope.loading = true;
if ($scope.formData.text != undefined) {
// call the create function from our service (returns a promise object)
Todos.create($scope.formData)
// if successful creation, call our get function to get all the new todos
.success(function(data) {
$scope.loading = false;
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos.unshift(data); // assign our new list of todos
});
}
};
// DELETE ==================================================================
// delete a todo after checking it
$scope.deleteTodo = function(id) {
$scope.loading = true;
Todos.delete(id)
// if successful creation, call our get function to get all the new todos
.success(function(data) {
$scope.loading = false;
$scope.todos = data; // assign our new list of todos
});
};
});
Here is what you would do.
Add a new field to schema to store the votes:
votes: {type: Number, default: 0}
Add a new handler on the server side to increment vote when it gets a request:
app.get('/api/todos/:todo_id/vote', function(req, res) {
Todo.update({_id: req.params.todo_id}, { $inc: {votes: 1} } ), function(err,doc){
...
}
}
Add a new function to AngularJS service to call this new API handler:
vote: function(id) {
return $http.get('/api/todos/' + id + '/vote');
}
Wire up ngClick on ngRepeated elements to call the new Svc function. NOTE: You would need Todos svc in your scope to do this as below, otherwise create a wrapper function in the scope as you have done.
<td>
<button data-ng-click="Todos.vote(todo._id)"
class="btn.." alt="Up vote this....">Vote
</button>
</td>
then display in your view somehow the new "votes" field of the ToDo Models coming back.
Check this out: http://meanjs.org/ You can get a lot of good examples working with Angular, node and Mongo, look at the "articles" module that comes with it.
I didn't try any of this but it should give you the basic idea what to do. Also, realize there is nothing here to stop a user from upvoting more than once. Hope it helps!

ExpressJS why is my GET method called after my DELETE method?

In my express app, when the DELETE method below is called, the GET method is immediately called after and it's giving me an error in my angular code that says it is expected an object but got an array.
Why is my GET method being called when i'm explicitly doing res.send(204); in my DELETE method and how can I fix this?
Server console:
DELETE /notes/5357ff1d91340db03d000001 204 4ms
GET /notes 200 2ms - 2b
Express Note route
exports.get = function (db) {
return function (req, res) {
var collection = db.get('notes');
collection.find({}, {}, function (e, docs) {
res.send(docs);
});
};
};
exports.delete = function(db) {
return function(req, res) {
var note_id = req.params.id;
var collection = db.get('notes');
collection.remove(
{ _id: note_id },
function(err, doc) {
// If it failed, return error
if (err) {
res.send("There was a problem deleting that note from the database.");
} else {
console.log('were in delete success');
res.send(204);
}
}
);
}
}
app.js
var note = require('./routes/note.js');
app.get('/notes', note.get(db));
app.post('/notes', note.create(db));
app.put('/notes/:id', note.update(db));
app.delete('/notes/:id', note.delete(db));
angularjs controller
$scope.delete = function(note_id) {
var note = noteService.get();
note.$delete({id: note_id});
}
angularjs noteService
angular.module('express_example').factory('noteService',function($resource, SETTINGS) {
return $resource(SETTINGS.base + '/notes/:id', { id: '#id' },
{
//query: { method: 'GET', isArray: true },
//create: { method: 'POST', isArray: true },
update: { method: 'PUT' }
//delete: { method: 'DELETE', isArray: true }
});
});
** UPDATE **
To help paint the picture, here's the angular error i'm getting:
Error: [$resource:badcfg] Error in resource configuration. Expected response to contain an object but got an array http://errors.angularjs.org/1.2.16/$resource/badcfg?p0=object&p1=array
I'm assuming that i'm getting this error because my delete method is calling my get method (somehow) and the get method returns the entire collection.
Server side
You're removing an element from a collection in your delete function. This is done asynchronously and calling your callback when it's finished.
During this time, other requests are executed, this is why your GET request is executed before your DELETE request is finished.
The same happens in your get function, you're trying to find an element from a collection and this function is too asynchronous.
But this is server side only and it is fine, it should work this way, your problem is located client side.
Client side
If you want to delete your note after you got it, you will have to use a callback function in your angular controller which will be called only when you got your note (if you need help on that, show us your noteService angular code).
This is some basic javascript understanding problem, actions are often made asynchronously and you need callbacks to have an execution chain.
Maybe try doing something like this:
$scope.delete = function(note_id) {
var note = noteService.get({ id: note_id }, function()
{
note.$delete();
});
}
Your code doesn't make sense though, why is there a get in the $scope.delete? Why not do as simply as following:
$scope.delete = function(note_id) {
noteService.delete({ id: note_id });
}
Error
I think you get this error because of what your server sends in your exports.delete function. You're sending a string or no content at all when angular expects an object (a REST API never sends strings). You should send something like that:
res.send({
results: [],
errors: [
"Your error"
]
});

Sails.js Set model value with value from Callback

i need to provide something like an association in my Model. So I have a Model called Posts with an userid and want to get the username from this username and display it.
So my ForumPosts.js Model looks like the following:
module.exports = {
schema: true,
attributes: {
content: {
type: 'text',
required: true
},
forumTopicId: {
type: 'text',
required: true
},
userId: {
type: 'integer',
required: true
},
getUsername: function(){
User.findOne(this.userId, function foundUser(err, user) {
var username = user.username;
});
console.log(username);
return username;
}
}
};
I know that this return will not work because it is asynchronus... But how can i display it in my view? At the Moment i retrive the value with:
<%= forumPost.getUsername() %>
And for sure get an undefined return...
So the question is: How can I return this value - or is there a better solution than an instanced Model?
Thanks in advance!
Off the top of my head, you can just load associated user asynchronously before rendering:
loadUser: function(done){
var that = this;
User.findOne(this.userId, function foundUser(err, user) {
if ((err)||(!user))
return done(err);
that.user = user;
done(null);
});
}
then in your controller action:
module.exports = {
index: function(req, res) {
// Something yours…
forumPost.loadUser(function(err) {
if (err)
return res.send(err, 500);
return res.view({forumPost: forumPost});
});
}
}
and in your view:
<%= forumPost.user.username %>
This is kind of a quick and dirty way. For a more solid and long-term solution (which is still in development so far) you can check out the alpha of Sails v0.10.0 with the Associations API.
So this particularly case of associations between your models. So here you have a User model and ForumPost model and you need the user object in place of your user_id as user_id works as a relationship mapping field to your User model.
So if your are using sails V0.9.8 or below you need to handle this logic in your controller where ever you want to access User model attributes in your view.
In your controller write your logic as:
model.export = {
//your getForumPosts method
getForumPosts : function(req,res){
var filters = {};
forumPost.find(filters).done(function(err,posts){
if(err) return res.send(500,err);
// Considering only one post obj
posts = posts[0];
postByUser(posts.user_id,function(obj){
if(obj.status)
{
posts.user = obj.msg;
delete posts.user_id;
res.view({post:posts});
}
else
{
res.send(500,obj.msg);
}
});
}
}
}
function postByUser(user_id,cb){
User.findOne(user_id).done(function(err,user){
if(err) return cb({status:false, msg:err});
if(user){
cb({status:true, msg:user});
}
}
}
and then you can access your post object in your view.
Or else you can keep watch (at GitHub) on next version of sails as they have announced associations in V0.10 n it is in beta testing phase as if now.

AngularJS redirection after ng-click

I have a REST API that read/save data from a MongoDB database.
The application I use retrieves a form and create an object (a job) from it, then save it to the DB. After the form, I have a button which click event triggers the saving function of my controller, then redirects to another url.
Once I click on the button, I am said that the job has well been added to the DB but the application is jammed and the redirection is never called. However, if I reload my application, I can see that the new "job" has well been added to the DB. What's wrong with this ??? Thanks !
Here is my code:
Sample html(jade) code:
button.btn.btn-large.btn-primary(type='submit', ng:click="save()") Create
Controller of the angular module:
function myJobOfferListCtrl($scope, $location, myJobs) {
$scope.save = function() {
var newJob = new myJobs($scope.job);
newJob.$save(function(err) {
if(err)
console.log('Impossible to create new job');
else {
console.log('Ready to redirect');
$location.path('/offers');
}
});
};
}
Configuration of the angular module:
var myApp = angular.module('appProfile', ['ngResource']);
myApp.factory('myJobs',['$resource', function($resource) {
return $resource('/api/allMyPostedJobs',
{},
{
save: {
method: 'POST'
}
});
}]);
The routing in my nodejs application :
app.post('/job', pass.ensureAuthenticated, jobOffers_routes.create);
And finally the controller of my REST API:
exports.create = function(req, res) {
var user = req.user;
var job = new Job({ user: user,
title: req.body.title,
description: req.body.description,
salary: req.body.salary,
dueDate: new Date(req.body.dueDate),
category: req.body.category});
job.save(function(err) {
if(err) {
console.log(err);
res.redirect('/home');
}
else {
console.log('New job for user: ' + user.username + " has been posted."); //<--- Message displayed in the log
//res.redirect('/offers'); //<---- triggered but never render
res.send(JSON.stringify(job));
}
});
};
I finally found the solution ! The issue was somewhere 18inches behind the screen....
I modified the angular application controller like this :
$scope.save = function() {
var newJob = new myJobs($scope.job);
newJob.$save(function(job) {
if(!job) {
$log.log('Impossible to create new job');
}
else {
$window.location.href = '/offers';
}
});
};
The trick is that my REST api returned the created job as a json object, and I was dealing with it like it were an error ! So, each time I created a job object, I was returned a json object, and as it was non null, the log message was triggered and I was never redirected.
Furthermore, I now use the $window.location.href property to fully reload the page.

Categories

Resources