How to access object set by server on client side - javascript

I'm using node with express and I want access object sent by server.
For example
server side:
router.get('/some_page/', (req, res) => {
res.render('some_page', {
data: {"somevar1":"somevalue", "somevar2":"somevalue2"}
});
});
client side javascript:
var objSentFromSrv = ??? // here i want this object and then perform some action on it
Is this possible/legitimate?
EDIT:
I'm using handlebars as template engine.
Figured out somehow.
function middlewareAppendingLocals(req, res, next) {
res.locals.layoutV = myValue;
next();
}
router.post('/page/', middlewareAppendingLocals, (req, res) => {
res.render('page_to_render');
});
In my case this variable is from database and I'm giving it based on id posted from antoher page. But still how can I access it from javascript, not only form .hbs layout file.
Then page_to_render have and I can you handlebars {{}} to get it.

You need to encode the object as JSON like this:
router.get('/some_page/', (req, res) => {
res.send(JSON.stringify({
data: {"somevar1":"somevalue", "somevar2":"somevalue2"}
}));
});
and then use AJAX on the front-end, using jQuery you can use
$.get('/some_page/', function(data) {
var objSentFromSrv = JSON.parse(data);
});
or shorter:
$.getJSON('/some_page/', function(data) {
var objSentFromSrv = data;
});

Yes. This is possible and legitimate. Assuming you are using EJS, add a line like this to your template:
<script>
const objSentFromSrv = <%-JSON.stringify(data)%>;
</script>
If you're using a different templating engine, you'll just need to look up the specific syntax on how to serialize objects.
AjAX is overkill for this use-case.

If you are using AngularJS as your front end service, you can create a controller and have it inject $scope and $http to get the data. For example:
var app = angular.module('myApp', []);
app.controller('mainController', ($scope, $http) => {
$scope.data= {};
$scope.getData = function() {
$http.get('/some_route/')
.success((data) => {
$scope.data = data;
console.log(data);
})
.error((error) => {
console.log(error);
});
};
});
And then in the front end, call getData().
https://docs.angularjs.org/guide/controller

Your templating engine is going to take the arguments passed to that render call and produce HTML (often) or JSON. It's not really sending objects, just text data.
If you're looking to change the state of some object that exists on the server side, you'll want to create some sort of API to do that. Send data down to the client, make changes to that data, then send it back to the server to be incorporated into the original object.

I am using Handlebar js and found to get server-side data at client side Javascript just using {{{ server-side JSON }}
`
Server-side Code send JSON adminData on the client side
return h.view('reports' ,{ adminData: request.auth.credentials});
Client side Code to get adminData inside script tag
console.log("{{{adminData}}}")

Related

How should I display data from backend in Node.js + jade + angularJS + mongoose

I'm going to make web application (SPA) with:
Backend: Node.js (express)
Frontend: Jade + AngularJS
Database: Mongoose
I will send data (as a form) to backend in this way ExpressJS AngularJS POST (Check ANSWER)
It will be simple CRUD.
However i wondering how should I display data from backend?
For example:
I'll run application
var Partner = require('../model/partners');
router.get('/', function (req, res) {
Partner.find({}, function (err, partnerList) {
if (err) throw err;
res.render('campaign', {
partnerList: partnerList
});
});
});
And how should i display data (partnerList). Maybe in this way?
- each item in partnerList
= item.name
Or maybe there is another better way with angular to display data at view? I'm asking because later i'd like remove or update items from partnerList (CRUD operation). And it may be a problem because i will have to send item._id as a parameter to angular function?
For example if i will add button to remove record:
- each item in partnerList
= item.name
button(type='remove' ng-click="sub('#{item._id}')")
script.
app.controller('view1Ctrl', function($scope, $http) {
$scope.sub = function(id) {
$http.post('/',id).
success(function(data) {
console.log("posted successfully");
}).error(function(data) {
console.error("error in posting");
})
}
});
Probably it won't work correct
As said in previous coment, from my point of view I prefere to send the minimum required data from the backend to the client, but it depends of you infrastructure and you concurrent users.
Example 1:
You have a web app with +5K concurrent users, in this case is better handle all the huge stuff at frondend side or you will need to spend a lot of money in your backend hardware.
Practical case:
Users POST a new comment in a blog page. You sanitize the text string at the backend and put it at you preferred datastore... But JUST respond with a simple json like {"status": "ok"}. If the frond end recive this, modify the DOM with the text string that the client sent to the backend in the POST stage, but not send again all the HTML with this (for example) 500 characters comment.
If server responds with {"status":"error"}, modify the DOM to let the user know what's the problem about his comment (more specified json message {"status":"error", "data":"you comment is bigger than 500 chars"})
Problems:
You need extra frontend code to handle these situations in the client side. So this "maybe" will inpact on the user the 1st time that it visits your page.
Pros:
Less hardware costs
Overall less server response times.
More user interactive website modeling only certain parts of the DOM at any moment.
...
Example 2:
You have a simple page with low concurrent users. Then you choose. Let you backend to handle everything? Or keep working with json responses?
I always use the 1st example. Hope this helps in your question.
I think the preferred method would be to set up a second route from express to specifically render JSON, then use angular's $http method to get that data and use it in your controller. If you want to do it with a single route, you can pass the JSON data as a string to your view on the server-side, but it might get a little unruly.
// app.js
...
partnerList: JSON.stringify(partnerList);
...
// index.jade
div(ng-repeat="item in partnerList")
p {{ item.name }}
button(type='remove', ng-click="sub(item._id)")
...
script.
app.controller('view1Ctrl', function($scope, $http) {
$scope.partnerList = JSON.parse(#{partnerList});
...
EDIT To use the JSON string example, you would have to render using the Unbuffered Code syntax. But I'm not sure how you would do that inside a script. block. To instead go the route of serving JSON separately, change your server routes to this:
var Partner = require('../model/partners');
router.get('/', function (req, res) {
res.render('campaign');
});
router.get("/partner-list", function(req, res) {
Partner.find({}, function (err, partnerList) {
if (err) throw err;
res.json({ partnerList: partnerList });
});
});
Then your angular code will query that /partner-list path with $http.get().
script.
app.controller('view1Ctrl', function($scope, $http) {
$http.get("/partner-list").then(function(result) {
$scope.partnerList = result.data.partnerList;
});
...
});

Routing in MEAN Stack - Routing help for Angular js and node.js using expressjs framework

I have solved the problem but I am still unsure if the way I am doing it is correct. If there is any alternative method via which I can send the file and data in one go then that would be more useful. Please give your inputs on the same.
I am using Angular js for the front end and Express js over node.js at the backend.
What I am trying to do?
I am trying to implement something like facebook's facility to provide you unique profile names or say user names.
Therefore - The user let's say types domain.com/hisprofileid
Now, what I want to do is a search should be done on the server side which would send response to front end with exact data depending upon the search's result.
and then front end will load the data.
What I have done till now?
Honestly speaking I haven't been able to think it out properly and the system I have put in place doesn't work.
This is what I have done. The root call that is localhost:portnumber on server side sends a file called index.html. This is just index file and nothing else.
Now on the server side I have made route to handle localhost:portnumber/anything which sends profilepage.html file as response.
Now the controller of that profilepage.html's controller using $locationprovider has this code to make a separate call to server side (Please refer to code below) [I strongly believe this is insignificant and that is why I'm lost]
Please look at some codes given below.
Front end part
$routeProvider
.when('/', {
templateUrl: 'index12.html',
controller: 'someCtrl'
})
.when('/:merchantid', {
templateUrl: 'index12.html',
controller:'userCtrl'
})
app.controller('userCtrl', function ($scope, Upload, $timeout, $http) {
console.log("Here");
var merchantid = "suresh";
$http.get('/merchant/' + merchantid ).success(function(response)
{
console.log("response");
console.log(response);
});
});
Server Side
app.get('/', function (req, res) {
console.log("Global");
res.sendFile(__dirname + '/public/index13.html');
});
app.get('/:merchantid', function (req, res) {
console.log("we are here");
console.log(req.params);
res.sendFile(__dirname + '/public/index12.html');
});
app.get('/merchant/:merchantid', function (req, res) {
console.log("Detail here");
console.log(req.params);
res.json({message: 'here'});
});
Please suggest something.
This is what I have done to solve the problem.
localhost:portnumber/anything - When this is called I am making a call to the server directly and a check is made if that particular person actually has signed up or not and then based on that result the appropriate page is opened.
app.get('/:profileid', route_profileid.fetchprofile);
Then the function to handle the data associated with it.
modename.findOne({
'profileid': uniqueid
}, function (err, docs) {
if (err) {
console.log("Error in finding data" + err);
} else {
if (docs) {
console.log(process.cwd());
res.sendFile(process.cwd() + '/public/profile.html');
}
if (!docs) {
console.log("Nothing Found related to that query");
res.sendFile(process.cwd() + '/public/error.html');
}
}
Now the profile page is loaded with profile data of that specific used and then here is the code of angular's router. [This angular code is attached to the profile page which will be shown.]
$rootScope.$on('$routeChangeSuccess', function () {
console.log($routeParams.profileid);
var profileid = $routeParams.profileid;
$http.get('/profile/' + profileid).success(function (response) {
console.log(response);
$scope.profile = response;
});
});
Note: Inclusion of $RouteParams, $route, $routeScope and ngRoute module to facilitate the activity is required.
Here a new request is made for the actual data of that user.
app.get('/profileid/:profileid', route_profiledata.profiledata);
and then in that specific function data is fetched from the db and appropriate response is sent back to the user.

Sending data (received from backend) from on html to another with angularJS

I feel like tons of people do this all the time, and yet I have been unsuccessful in finding similar examples.
I am getting data from the backend using angularJS ($http.post) to a controller in a javascript file, and presenting it in one html. The data is received after sending a search query from that html. Now, I want to "export" that data to another JS file and to present some of it again, in a new html. The problem is that I have access to that data only through the Search Controller during the searching session, and I probably need to store it somehow or send it to another controller/ JS file.
Unfortunately, I cannot use $cookies. Also, I am trying to avoid sending a new request through the server if I don't have to.
I have read a some about services in angular, however, I am new to angular (and UI in general), and for some reason was unable to implement this for my specific case.
Here is an example of the relevant controller, after getting a search request from the html page:
app.controller('SearchCtrl', ['$scope', '$http',
function($scope, $http) {
$scope.searchJSON = {
searchToken: [],
searchOption: []
$scope.sendSearch = function() {
//preparing JSON to send request to server
$scope.searchJSON["searchToken"] = this.search.searchToken;
$scope.searchJSON["searchOption"] = this.search.searchOption;
var json = $scope.searchJSON;
//sending and getting response (JSON object)
$http.post("http://some_host", json)
.success(function(response) {
$scope.collections = response.searchResults;
});
};
}]);
So the data I am interested in passing on to another JS file is in $scope.collections , which is a JSON file (I don't want use the same JS file for both html pages, so was hoping to call that data from a new controller in a new JS file).
Will appreciate any answers, leads, or similar examples from the web. Thank folks!
One possible way to solve this is by using sessionStorage/localStorage on $window. You can store your data there and after redirecting to another file, you can use it by invoking.
You are right to bring up services because that is how I would personally implement this. Create a service to handle the search request and also to store the result via promises:
angular.module('yourModule')
.factory('searchService', function($http, $q) {
var searchService = {
resultsPromise: null,
sendSearch: function(token, option) {
var dfd = $q.defer();
var json = {
searchToken: token,
searchOption: option
};
$http.post("http://some_host", json).then(
function(response) {
// resolve your deferred
dfd.resolve(response.data);
},
dfd.reject
);
this.resultsPromise = dfd.promise;
return dfd.promise;
}
};
return searchService;
});
Then in your current controller, just do:
app.controller('SearchCtrl', ['$scope', 'searchService',
function($scope, searchService) {
$scope.searchJSON = {
searchToken: [],
searchOption: []
$scope.sendSearch = function() {
searchService.sendSearch($scope.searchJSON.searchToken, $scope.searchJSON.searchOption);
};
Then in your other file, simply look at the currentResults of the same service:
app.controller('OtherCtrl', function($scope, searchService) {
if (searchService.resultsPromise) {
searchService.resultsPromise.then(function(results) {
$scope.results = results;
});
}
});
You can ditch the $http service and use $resource instead. From there you can use $cacheFactory as seen in this post: How to cache an http get service in angularjs
An alternative solution is http://jmdobry.github.io/angular-cache/ which works well with ngResource and can also easily be configured to sync to localStorage, so requests don't need to be re-done after page refresh.
`$resource('my/kewl/url/:key', { key: '#key' }, {
'get': { method: 'GET',
cache: $angularCacheFactory('MyKewlResourceCache', {
storageMode: 'localStorage' })
}
});`

Stormpath Custom Data

I requested stormpath user custom data by using
res.render('home', {
title: 'home',
user: req.user.customData,
});
i expected to receive a json object of custom data but instead a url ('https://api.stormpath.com/v1/accounts/WvtGbIH3kJ4rEttVF5r9U/customData') was returned. This page does have the custom data i want on it but i cannot request it using an ajax request as it is a https page. What should I do? Thanks in advance
You'll need to use the "auto expansion" feature of the library, like this:
app.use(stormpath.init(app, {
expandCustomData: true,
});
That will expand the custom data resource for you. By default it's just a link to the resource, as you've seen.
Found the best way to request custom data is to use the getCustomData() method in the route, set the data to a variable and use a get request from the client to request this data as in the sample below:
Server Js
customData = new Array;
router.get("/string", function(req, res) {
req.user.getCustomData(function(err, data) {
customData = data.someKey;
})
res.send(customData) /*Returns Empty Arrray*/
})
router.get("/cdata", function(req, res) {
res.send(customData) /*Sends Actual Custom Data*/
})
Client Js
var customData = new array
$(document).ready(function() {
$.get("/string", function(string) {
/*Tells server to get customData*/
})
$(document).click(function(){
if(pleaseCount===0){
$.get("/cdata", function(data) {
for(i=0;i<data.length;i++){
customData.unshift(data[i])
pleaseCount=pleaseCount+1
/*Custom data is now stored in client side array*/
}
})
}
})
That's what worked for me anyway. I don't know why someone down-voted the question as this is an acceptable way to retrieve other user information such as name and email by using userName:req.user.userName in the render function and rendering this information to a p. tag in a jade page by using p #{userName}

Easy way to handle post data in meteor.js?

I need to handle some POST data in my meteor.js app, is there an easy way to do this?
Very basic, if it was a PHP app I would just want the $_POST variable.
Meteor router
https://github.com/tmeasday/meteor-router#server-side-routing
Meteor.Router.add('/items/:id', 'POST', function(id) {
// update Item Function
return [200, 'ok'];
});
If you are simply looking to intercept the GET and POST data, then send Meteor on it's merry way, you could do something like this on the server.
if (Meteor.isServer) {
var connect = Npm.require('connect');
var app = __meteor_bootstrap__.app;
var post, get;
app
// parse the POST data
.use(connect.bodyParser())
// parse the GET data
.use(connect.query())
// intercept data and send continue
.use(function(req, res, next) {
post = req.body;
get = req.query;
return next();
});
Meteor.startup(function() {
// do something with post and get variables
});
}
EDIT 11/01/13
I ended up creating a smart package for this (for myself). There is no documentation but you are welcome to use it. https://github.com/johnnyfreeman/request-data
To retrieve the foo request variable:
RequestData.get('foo') // --> 'bar'
RequestData.post('foo') // --> 'bar'
Both methods will throw a Meteor.Error if the key isn't found so make sure you use wrap with a try/catch if the variable is optional.
You can use Meteor's Iron Router, docs here, since Router (as mentioned above) is outdated and might be no longer functional.
Router.route('/items/:id', {where: 'server'})
.get(function () {
this.response.end('get request\n');
})
.post(function () {
this.response.end('post request\n');
});
I'm using this package to serialize body data: simple:json-routes. Here is the link.
And this code snippet to access it:
WebApp.connectHandlers.use('/api/request', (req, res, next) => {
console.log(req.body);
});

Categories

Resources