Angular ngInit formatting - javascript

I'm building a MEAN app and I'm trying to pass in data from the server-side into the angular application and I've read that this is possible with the use of ngInit but I'm having a lot of trouble with getting it to work.
My Express route is set up as follows:
app.get('/dashboard', Auth.ensureAuthenticated, function (req, res) {
res.sendfile('./app/views/admin.html', req);
console.log(req.user);
});
The console log message is there for production reasons so I can see the current authenticated user in the terminal.
Now when I try to pass req into ngInit and I'm getting tonnes of errors. If my body is set up like:
<body class="dashboard" ng-controller="DashboardController as dashboard" ng-init="active_user = {req.user}"> ... </body>
This causes angular to spit out:

It looks like you're sending a plain html file with res.sendfile(…) and expecting Express to interpolate a variable.
In order to do what you're asking you'll need to do some server-side templating. It looks like res.render('admin', {user: req.user}); will do the trick, assuming you've modified your admin view to be a proper template.

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;
});
...
});

Node.js: Returning proper JSON from mongoose query

I have this express application with mongoDB as the database and handlebars as my server-side templating engine. I am not using AngularJS or Ajax in my application.
In one of the routes, I have to render the page as well as send over a json file from the database. However, I am not able to achieve this.
Here is code snippet the my route:
router.get('/disks', function(req, res, next) {
places.find({"category": "disks"}, function(err, disks){
if(err){
throw err;
}
res.render('disks',
{
'risime': JSON.stringify(disks)
});
console.log(disks); // PROPERLY LOGS TO THE CONSOLE
});
});
In the hbs, I am trying to capture it, but I don't even think that it is JSON.
Here is how it gets logged in the client side:
[{"_id":"5704630a7d4cd367f8dsdce7","name":"Seagate",:"This awesome Hard disk",","categories":["SDD","256GB"]}]
What is the issue and how do I resolve it?
It's handlebars that "html escapes" your string (which is what you normally want).
if you don't want that, you can use the "triple-stash" notation, like this:
{{{risime}}}
You can read about this here: http://handlebarsjs.com/#html-escaping
I think you need to add this before render:
res.type('application/json');
The client will know this is a JSON, not a HTML or a plain text and it will be shown correctly.
I hope my answer will help you.

How to pass request parameters back to Angular

I currently have an app which uses Express with Jade templates.
I'm building a new version of the app using Angular with client-side HTML.
I need access to certain request parameters in order to determine user permissions in my Angular code. My problem is that I don't know how to get ahold of these parameters in my Angular controllers/services.
Below is what currently occurs in Express with the Jade structure:
routes.js:
router.get('/player/:id',
playerRoute.show
);
player.js:
var show = function(req, res) {
res.render('player', {user: req.user});
};
...and now my new version's handler:
var player = function(req, res) {
//res.sendFile(path.join(__dirname, '../v2', 'index.html'));
res.json({user: req.user});
};
The correct user JSON is sent back to my client-side with the code above. When res.json is commented out and res.sendFile uncommented the correct HTML is rendered. My dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
After all that, your question just boils down to:
MY dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
You don't. The usual case is to just render the HTML along with the assets needed to render the initial app (hide everything, show a splash screen whatever). Further data (like getting your user) is handled by API calls to your server via Angular's HTTP facilities. That means they are separate. After that API call, your app determines what to render.
Otherwise, you could just render the data in the HTML as some global variable and have Angular pick it up from there. This is messy IMO, but doesn't require a separate API call to get the data.
copied from my own answer to a similar question
To get a variable from server to client javascript try templating a json string into the html and loading it from the javascript. EJS handles quote escaping and I think Jade does too. For reference content!= safeString tells Jade to skip escaping, so does content !{safeString}.
- var user={id:1, displayName:'foo'}
#example
meta(data-userJSON=JSON.stringify(user))
script(src="//code.jquery.com/jquery-1.11.3.min.js")
script.
var user = JSON.parse(
$('#example meta').attr('data-userJSON')
)
console.log(user);
span #{user.id}
span #{user.displayName}
Here's how I ended up handling this situation. I simply created a new API endpoint which I can easily hit with an Angular service. Here's the Node setup:
routes.js:
router.get('/currentUser',
apiController.currentUser.index
);
currentUser.js:
var index = function(req, res) {
res.json({user: req.user});
};
module.exports = {
index: index
};
Still seems odd to me to make an API call to get the request parameters, but it works. Feedback appreciated.

AngularJS unwanted Behavior when reloading page

I'm developing an Angular application with the MEAN stack, so suppose you got an express route that make a query to the databse, the results are sent in the response:
app.get('/api', function(req, res){
Todo.find({}, "", function(err,todos){
if (err)
res.send(err);
res.json(todos);
});
});
In the client-side:
Controller :
...
Todo.get().success(function(data){ //i got the service with the $http call
$scope.todos = data;
});
When I go to localhost:8080/#/api, I can see my partial and the data I requested.
The problem that I'm having is that if I omit the hashtag, i don't see the partial, I only see the response data in JSON format.
I also tried to use html5 mode, but if I reload I got the same behavior.
Any ideas on how can I avoid this behavior??
Anything after the # isn't sent to the server. So when you go to localhost:8080/#/api, expressjs just sees a request to / and returns the AngularJS template. AngularJS then routes the browser page using the /#/api, which called the Todo.get() and (I assume) makes a call to localhost:8080/api, returning the data from the DB.
That's why you only get the data when you omit the hash and when you use html5 mode.
I would suggest changing your API call to:
/api/todos - return data from the db
And change your AngularJS route to just use:
/todos - show the partial and data requested

Sails.js index.ejs controller logic

I'm a little confused on how to add logic to the home page of my Sails.js app. Right now, its just a static page, but I would like to include data on the homepage (index.ejs). I have a MainController and I included a index: function that is pulling in the data. I can't figure out how to configure my route to allow for this.
From What you wrote I am guessing you are using Express js and ejs template.
If you are using the Express render method in your mainController to render your index.ejs you can send the data with response like:
res.render('index', { data: 'my data' }, function(err, html){
// handle callback and error
});
so here you have sent some data
then in your index.ejs file you can get data using ejs tags like:
<div><%= data %></div>
Tell me more about your mainController method if this is not useful
The static-folder is for static-content only (as the name is telling us). If you want your website to show content dynamically you need to create a controller like that:
module.exports = {
index: function(req, res){
res.view(); // sending the view in /views/{controller_name}/index.ejs
return;
}
}
Cheers!

Categories

Resources