1
votes

I have this AngularJS SPA with ui-router which works perfectly. It uses parse.com as the backend, and I have it working on a regular Apache server.

Now I want to move it to a node.js server-app, and I want node.js to handle all the CRUDs for parse.com.

I set up a nice little node.js app to act as server, and it works.

My question is: How do I handle requests between my node.js server-app and my AngularJS SPA?

I've included my server.js file, in case anyone can use it.

// set up =====================================================================================================
var express			= require('express'),
	path			= require('path'),
	morgan			= require('morgan'),
	bodyParser		= require('body-parser'),
	methodOverride	= require('method-override'),
	routes			= require('routes'),
	keys			= require('./config/keys'),
	port			= 80;

var app = express();

var Parse = require('parse/node').Parse;

// view engine setup ==========================================================================================
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// configuration ==============================================================================================
app.use(require('prerender-node').set('prerenderToken', keys.prerender));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({'extended':'true'}));            // parse application/x-www-form-urlencoded
app.use(bodyParser.json());                                     // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(methodOverride());
app.use(express.static(path.join(__dirname, 'public_html')));

Parse.initialize(keys.app, keys.js);

// routing ====================================================================================================
app.use(function(req, res) {
	"use strict";
    // use res.sendfile, as it streams instead of reading the file into memory. ===============================
    res.sendfile(__dirname + '/public_html/index.html');
});

app.use('/', routes);

// catch 404 and forward to error handler =====================================================================
app.use(function(req, res, next) {
	"use strict";
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// listen (start app with node server.js) =====================================================================
app.listen(port);
console.log("App listening on port %d", port);

File structure:

- public_html/ <-- the angularjs app -->
- node_modules/ <-- installed modules for node -->
- config/
    - keys.js
- server.js
- package.json

The current setup

So, currently, I would deal with parse.com data in my (angularjs) app controller - and some of it in parse's cloud-code.

Now, I want to move all parse.com dealings to my node.js server-app, so that my angularjs "calls" the node.js server-app, which in turn "calls" parse.com for the data I need, and then return it to the angularjs app so I can update my views (with the new data from parse.com).

Example of what I want

parse.com <--> node.js server-app <--> angularjs SPA (views)

A simple thing I do in my controller is something like

var Profile = Parse.Object.extend('Profile');
var query = new Parse.Query(Profile);
query.equalTo('objectId', $stateParams.authorPermaLink);
query.find().then(function(results){
  var object = results[0];
  $scope.authorObj = results[0];
  $scope.template.pageName = object.get('screenname');
  $scope.template.pageAuthor = object.get('screenname');
  $scope.template.pagePublished = object.createdAt;
  $scope.template.pageLastEdit = object.updatedAt;
  $scope.$apply();
}, function(error){
  // error-handling
  console.log("Error: " + error.code + " " + error.message);
});

Now, moving this snippet of code to node.js is simple because I can use the parse.com SDK in node.js directly. But how do I get the angularjs app to communicate with the node.js server-app?

1
Need to be a lot more specific as to what problem you have setting this up - charlietfl
Alright, I'll add some more specifics as to what I need... I was, however, trying to keep the question general - being this is stackoverflow... - Brian Emilius
Well too general can make question too broad. Shouldn't be difficult to set up endpoints (routes) in node for each of your collection types in parse. Also would point at parse REST from node not the javascript sdk - charlietfl
Yeah I looked at parse's REST API, but it still leaves the question as to how I make angular and node communicate the parse.com data. Basically, I am at a loss about how to do what you're suggesting... - Brian Emilius
What is reason for not using parse directly in page? Using node you would really just be setting up a proxy that would pass identical data right through - charlietfl

1 Answers

0
votes

Okay, so I managed to brain my way out of this.

The solution is to make routes that will handle http-requests from my angularjs app.

routes.js (node):

app.get('/api/article/:permalink', function(req, res) {
    blog.getArticle(req.params.permalink, function(data) {
        res.json(data);
    });
});


// everything else
app.use(function(req, res) {
  // use res.sendfile, as it streams instead of reading the file into memory.
  res.sendfile('./public_html/index.html');
});

Then create a model with the blog object and methods, which are called above.

model.js (also node):

module.exports = {

  getArticle : function(permalink, callback) {
    "use strict";
    var Article = Parse.Object.extend('Article');
    var query = new Parse.Query(Article);
    query.include('category');
    query.include('profile');
    query.equalTo('permalink', permalink);
    query.find().then(function(results) {
      var result = results[0];
      var object = {
        title: result.get('title'),
        screenname: result.get('profile').get('screenname'),
        profileID: result.get('profile').id,
        content: result.get('content'),
        publishedAt: result.get('publishedAt'),
        updatedAt: result.updatedAt,
        categoryName: result.get('category').get('categoryName'),
        categoryPermaLink: result.get('category').get('categoryPermaLink'),
        articleID: result.id
      };

      callback(object);
      
    }, function(error) {
      callback({error: error});
    });
  }

};

And then finally in mu angularjs app, simply make a http-request (get in this example but the other rest verbs all work as well).

controller.js (angularjs):

$http.get('/api/article/' + $stateParams.articlePermaLink
         ).then(function successCallback(response) {
  response = response.data;
  $scope.articleTitle = response.title;
  $scope.template.pageName = response.title;
  $scope.articleAuthor = response.screenname;
  $scope.template.pageAuthor = response.screenname;
  $scope.profilePermaLink = response.profileID;
  $scope.articleContent = response.content;
  $scope.publishDate = response.publishedAt;
  $scope.template.pagePublished = response.publishedAt;
  $scope.template.pageLastEdit = response.updatedAt;
  $scope.category = response.categoryName;
  $scope.categoryPermaLink = response.categoryPermaLink;
  $scope.currentArticle = response.articleID;

  console.log(response.commentObj);

}, function errorCallback(response) {
  console.log("Error: " + response.code + " " + response.message);
});

The callbacks are the magic!