RESTful CRUD for Angular and Express $resource - node.js

I have my JSON querying and creating correctly. I'm a bit stuck on how to remove items from the server. They are being removed in angular but I can't seem to get the connection right for removing them on the server.
My server.js:
var hcController = require('./server/controllers/services-controller.js')
//REST API
app.get('/api/hc', hcController.list);
app.post('/api/hc', hcController.create);
app.delete('/api/hc:_id', hcController.delete);
My server-side model
var mongoose = require('mongoose');
module.exports = mongoose.model('HealingCenterData',{
title: String,
shortname: String,
summary: String,
description: String
});
My server-side controller
var Hc = require('../models/healingcenter-model.js')
module.exports.create = function (req, res) {
var hc = new Hc(req.body);
hc.save(function (err, result){
res.json(result);
});
}
module.exports.list = function (req,res) {
Hc.find({}, function (err, results){
res.json(results);
});
}
module.exports.delete = function (req, res) {
???????
});
}
My angular service:
app.factory("HC", ["$resource", function($resource) {
return {
API: $resource('/api/hc/:id')
}
}]);
My angular controller:
app.controller('servicesController', ['$scope', 'HC','$resource', function ($scope, HC, $resource) {
HC.API.query(function(results) {
$scope.services = results;
});
$scope.createService = function() {
var service = new HC.API();
service.title = $scope.serviceTitle;
service.shortname = $scope.serviceShortname;
service.summary = $scope.serviceSummary;
service.description = $scope.serviceDescription;
service.$save(function(result){
$scope.services.push(result);
$scope.serviceTitle = '';
$scope.serviceShortname = '';
$scope.serviceSummary = '';
$scope.serviceDescription = '';
});
}
$scope.removeItem = function(index){
$scope.services.splice(index, 1);
}
}]);
My JSON structure
{ "_id" : ObjectId("53bea9366a03a66c2dad68bb"), "title" : "Auto Clinic", "shortname" : "auto_clinic", "summary" : "Volunteers evaluate car problems and make minor repairs. Labor is free, and the car owner pays for any needed parts. Oil changes are performed at a reduced cost. All services are performed on Saturdays.", "description" : "No additional information yet.", "__v" : 0 }

On the server side try (I'm assuming you are using moongose) :
exports.delete = function(req,res){
if(req.params.id !==null || req.params.id!==undefined){
Hc.remove({_id:req.params.id},function(err){
res.send(200);
});
}
};
on the client side:
angular controller:
var endPoint = $resource('/api/hc/:id', {id:'#tId'});
$scope.removeItem = function(id){
var ep = new endPoint({tId:id});
ep.$delete(function(res){
//TODO: update local array in scope
});
};
EDIT:
you can just use the resource directly in the controller or just the service as you have done in your case, that's totally fine.

Related

Multiple queries in documentdb-q-promises for Nodejs

I want to render a page getting info for two different queries in CosmoDB using documentdb.
I have 2 queries:
var FirstQuery = {
query: 'SELECT * FROM FactoryData',
};
var SecondQuery = {
query: 'SELECT * FROM StoreData',
};
And have this to get the data
docDbClient.queryDocuments(collLink, FirstQuery ).toArray(function (err, results) {
value1 = results;
});
docDbClient.queryDocuments(collLink, SecondQuery ).toArray(function (err, results) {
value2 = results;
});
then i want to render the view with those results but i cant get it rendering from outise of this funcions.
res.render('view.html', {"value1" : value1 , "value2" : value2});
I know that this code will not work, but i was trying to implement promises and didn't know how to do it with documentdb-q-promises.
I already read a lot of documentation about Q promise but i dont get it.
Can someone explain to me how i can do it , I`m a beginner.
Based on your requirements,I followed the npm doc and test code on github to test following code in my local express project. Please refer to it.
var express = require('express');
var router = express.Router();
var DocumentClient = require('documentdb-q-promises').DocumentClientWrapper;
var host = 'https://***.documents.azure.com:443/'; // Add your endpoint
var masterKey = '***'; // Add the massterkey of the endpoint
var client = new DocumentClient(host, {masterKey: masterKey});
var collLink1 = 'dbs/db/colls/import';
var FirstQuery = 'select c.id,c.name from c';
var collLink2 = 'dbs/db/colls/item';
var returnArray = [];
client.queryDocuments(collLink1, FirstQuery).toArrayAsync().
then(function(response){
console.log(response.feed);
var map = {};
map['value1'] = response.feed;
returnArray.push(map);
return client.queryDocuments(collLink2, FirstQuery).toArrayAsync()
})
.then(function(response) {
console.log(response.feed);
var map = {};
map['value2'] = response.feed;
returnArray.push(map);
})
.fail(function(error) {
console.log("An error occured", error);
});
router.get('/', function(req, res, next) {
res.send(returnArray);
});
module.exports = router;
Test Result:
Hope it helps you.

Mongoose.create creating document but none of my data

I'm learning to use the mean stack and trying to build a url shortener. I've got a module that takes the req.params.UserUrl checks and makes sure it's a valid url then creates a random number that I want to use as the short route. I can't seem to find a way to save the random number so that I can check their next url request against it. After a google search it seemed maybe the most effecient way would be to save an object in the database with the long_url and the short_url:randomNumber. My code doesn't throw any errors but when I check my heroku database it has a new entry but only has the _id and __v that mLabs generates itself. Can someone tell me where I'm going wrong.
Route File
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var URLShortener = require(process.cwd()+'/public/Modules/urlShortener.module.js');
var ShortURL = require('../models/shortUrl.js');
router.get('/', function(req, res) {
res.render('index', { title: 'FreeCodeCamp Projects' });
});
router.get('/urlShortener', function(req, res){
res.render('freecodecamp/urlShortener', { title: 'Url Shortener Site'});
});
router.get('/urlShortener/:userUrl', function(req, res){
if(URLShortener.checkValidUrl(req.params.userUrl))
{
var UserUrl = req.params.userUrl;
var randNbr = URLShortener.assignRanNbr();
ShortURL.create(URLShortener.createUrlObj(UserUrl, randNbr), function (err, smallUrl) {
if (err) return console.log(err);
else res.json(smallUrl);
});
}
else
{
res.send('Invalid url');
}
});
router.get('/:short', function(req, res){
if(randNbr == req.params.short)
{
res.redirect(userUrl);
}
else
{
res.send('Not the correct shortcut');
}
});
module.exports = router;
Url Schema
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var shortUrlSchema = new Schema({
long_id:String,
short_id:Number
}, {collection: 'shortUrl'});
module.exports = mongoose.model('shortUrl', shortUrlSchema);
urlShortener Module
'use strict'
module.exports.checkValidUrl = function(url){
var pattern = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+#)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+#)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%#.\w_]*)#?(?:[\w]*))?)/);
return pattern.test(url);
}
module.exports.assignRanNbr = function(){
var randNbr = Math.floor(Math.random() * (9999 - 1 + 1)) + 1;
return randNbr;
}
module.exports.createUrlObj = function(url, num){
var urlObj = {};
urlObj.original_url = url;
urlObj.short_url = 'https://rawlejuglal-me-rawlejuglal-1.c9users.io/freecodecamp/'+num;
return urlObj;
}
Your createUrlObj method is returning an object with the properties original_url and short_url, but your shortUrlSchema properties are long_id and short_id. The property names in your create method need to match your schema. The property value types must also match your schema types (currently short_url is a string and short_id is a number). I think what you really want is for your createUrlObj method to be
module.exports.createUrlObj = function(url, num){
var urlObj = {};
urlObj.long_url = url;
urlObj.short_id = num;
return urlObj;
}
and your schema to be
var shortUrlSchema = new mongoose.Schema({
long_url: String,
short_id: Number
}, {collection: 'shortUrl'});
Additionally, your '/:short' route should have a call to the database since the randNbr and userUrl variables are not defined in that route.
router.get('/:short', function(req, res){
ShortUrl.findOne({short_id: req.params.short}, function(err, shortUrl){
if(err) res.send('Invalid Url');
res.redirect(shortUrl.long_url)
})
});

How to Auto-refresh the list of all imported data in MEAN stack. Nodejs+Mongodb+Openshift

I have a form, which a user inserts product data in the databse. When the save button is pressed, the method POST occurs. After the Post, the GET method, is called. Apparently, this works in localhost but on Openshift the POST is executed but the list does't auto refresh.
Server.js (GET, POST method)
var ResourcesSchema = new mongoose.Schema({
name: String,
serialnumber: String,
modelno: String,
description: String
});
var Resources = mongoose.model("Resources", ResourcesSchema);
app.get("/resources", function(req, res){
Resources.find(function(err, resources)
{
res.send(resources);
});
});
app.post("/resources", function(req, res){
var resources = new Resources(req.body);
resources.save(function(err, doc){
console.log(doc);
res.json(doc);
});
});
resources.js
app.controller("ResCtrl", function($scope, $http) {
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
$scope.addResource = function() {
console.log($scope.resource);
$http.post('/resources', $scope.resource)
.success(function(response){
$scope.resources.push(response);
});
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
};
});
Found the solution:
Had to do a function named $scope.all to retrieve data from the database and i had to call it from inside the $scope.addResource function:
$scope.addResource = function() {
console.log($scope.resource);
$http.post('/resources', $scope.resource)
.success(function(response){
$scope.resources.push(response);
$scope.all();
});
};
$scope.all = function(){
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
};
so if i make a post to db, the $scope.all(); will auto-refresh the list
I would suggest to make GET request after successful POST. You may get not updated data because GET request happens before data saved into database (we are dealing with asynchronous behavior here).
app.controller("ResCtrl", function($scope, $http) {
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
$scope.addResource = function() {
console.log($scope.resource);
$http.post('/resources', $scope.resource)
.success(function(response){
//$scope.resources.push(response); /*not sure we need this*/
// will make get call only after data saved successfully
$http.get('/resources')
.success(function(response) {
var resource = "";
$scope.resources = response;
$scope.resource = "";
});
}, function(err){console.log(err);});
};
});

angularjs error on server callback

I'm making a call to the server using resource and when I go to the base URL of
/viewEvent
It works fine. I receive all the database entries. However, when I go to
/viewEvent/1234
where 1234 is the eventID
I get a undefined is not a function and this is a crash from within angular. Stack trace is
TypeError: undefined is not a function
at copy (http://localhost:8000/js/lib/angular/angular.js:593:21)
at http://localhost:8000/js/lib/angular/angular-resource.js:410:19
at wrappedCallback (http://localhost:8000/js/lib/angular/angular.js:6846:59)
at http://localhost:8000/js/lib/angular/angular.js:6883:26
at Object.Scope.$eval (http://localhost:8000/js/lib/angular/angular.js:8057:28)
at Object.Scope.$digest (http://localhost:8000/js/lib/angular/angular.js:7922:25)
at Object.Scope.$apply (http://localhost:8000/js/lib/angular/angular.js:8143:24)
at done (http://localhost:8000/js/lib/angular/angular.js:9170:20)
at completeRequest (http://localhost:8000/js/lib/angular/angular.js:9333:7)
at XMLHttpRequest.xhr.onreadystatechange (http://localhost:8000/js/lib/angular/angular.js:9303:11) angular.js:575
When I examine the server, the request was made correctly. I can see that it got 1234 and it pulls the correct entry from the mongo database.
This is the controller logic
.controller("viewEventsController", ["$scope", 'EventService', '$location', function($scope, EventService, $location){
var path = $location.path().split('/');
var pathSize = path.length;
$scope.events = [];
if(pathSize === 2){
console.log("No event ID");
$scope.events = EventService.query();
}
else{
console.log("Event ID specified");
EventService.get({"eventID": path[pathSize - 1]}, function(data){
//$scope.events.push(data);
console.log(data);
}, function(error){
console.log(error);
});
}
}]);
and the service logic
service.factory('EventService', function($resource){
return $resource('api/viewEvent/:eventID');
});
It never makes it back to the controller so I'm "confident" it's not that. (watch it be that)
Not sure if the best way, but I got it working by doing
In service:
service.factory('EventService', function($resource){
return $resource('api/viewEvent/:eventID',
{eventID:"#eventID"},
{
'getSingleEvent': {
url: "api/viewEvent/:eventID",
method: "GET",
isArray: true
}
}
);
controller
var path = $location.path().split('/');
var pathSize = path.length;
EventService.getSingleEvent({"eventID":path[pathSize - 1]}, function(result){
$scope.updateEvent();
});
Server
routes = require('./routes')
var router = express.Router();
router.get('/api/viewEvent/:eventID', routes.viewEvent);
and in the routes directory I have a js file with
var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'eventApp');
var eventSchema = require('../models/createEvent.js').eventSchema;
var event = db.model('events', eventSchema);
exports.viewEvent = function(req, res){
console.log(req.params.eventID);
if(req.params.eventID) {
event.find({"_id": req.params.eventID}, function (error, events) {
console.log(events);
res.send(events);
});
}
else{
event.find({}, function (error, events) {
console.log(events);
res.send(events);
})
}
};

Get model from mongoose db

I'm currently looking into building a small REST based service to which I can POST some data into a mongoose db and GET the data back.
Here's my main.js file:
var http = require("http");
var DAO = require("./DAO");
var express = require("express");
var util = require('util');
var app = express();
app.use(express.bodyParser());
app.post('/postIsles',function(req,res){
DAO[req.method](req.body);
res.send("body" + req.body.name);
});
app.get('/getIsles',function(req,res){
var isleVar = DAO[req.method](req);
res.send(isleVar);
});
app.listen("3000");
console.log("\nApp available at http://127.0.0.1:3000\n");
And DAO.js:
var mongoose = require('mongoose');
//Connect to database
mongoose.connect( 'mongodb://127.0.0.1:27017/library_database' );
//Schemas
var Isle = new mongoose.Schema({
name: String,
description: String,
lastStocked: Date
});
//Models
var IsleModel = mongoose.model( 'Isle', Isle );
function POST(request) {
var name = request.name;
var description = request.description;
var lastStocked = request.lastStocked;
console.log("POST REQ +" + request);
var isle = new IsleModel({
name: name,
description: description,
lastStocked: lastStocked
});
isle.save( function( err ) {
if( !err ) {
return console.log( 'created' );
} else {
return console.log( err );
}
});
}
function GET(request) {
return IsleModel.find( function( err, islesT ) {
if( !err ) {
console.log("isles :"+islesT);
return islesT;
} else {
return console.log( err );
}
});
}
exports.POST = POST;
exports.GET = GET;
When I try to run the GET, I get the following error:
TypeError: Converting circular structure to JSON
at Object.stringify (native)
I'm a bit unsure how to overcome this.
Remember when using Node.js: any operation that involves IO will be asynchronous.
Model#find is an asynchronous method, so isleVar is not set to the result you're expecting. Your result will only be available inside of the anonymous function that you pass into IsleModel.find
To fix your GET method, you'll need to modify your code to take into account the asynchronicity of the DB request and only send the response once your app has had a chance to retrieve data.
Below, is an example of one possible solution to fix /getIsles:
In main.js, modify your get route to pass in res (so it can be handled asynchronously)
app.get('/getIsles',function(req,res){
return DAO[req.method](req, res);
});
In DAO.js, have response send the data inside of your callback to IsleModel.find
function GET(request, response) {
IsleModel.find( function( err, islesT ) {
if( !err ) {
console.log("isles :"+islesT);
response.send(islesT);
} else {
return console.log( err );
}
});
}

Resources