I need to define the skeleton for my node.js app with a menu that needs to be different for logged and anonymous user.
I think that the correct way should be the use of partials (i use Express 2.5) but i don't know how to pass data from the app and the partial. Do i need to add a condition in the layout to embed loggedPartial.ejs or anonymousPartial.ejs?
I'm sure there must be a cleaner way to do it.
In your route:
res.render('main', { menu : 'loggedPartial' }); // or 'anonymousPartial'
Your main template:
<%- partial(menu) %>
No need to use a conditional statement, menu is expanded dynamically during rendering.
Related
I need to access the variable user in my client-side that sent by
res.render('home.html', { user: req.user });
without using template engines like pug or ejs
Is that possible?
HTML is not a templating language, so it can't be used to send variables.
res.render() function compiles your template , inserts locals there, and creates html output out of those two things. The syntax is as follows -
res.render(view [, locals] [, callback])
The view argument is a string that is the file path of the view file to render. For this to work, you need a template or view engine .
In html, you can't dynamically pass/insert data variables. That's the main use case for templating engine. They put runtime/dynamic value in html which is what you are probably looking for.
In short, its better to use any template engine like pug,jade,ejs, etc most of which would have almost similar syntax with html to render dynamic html pages. I don't think there's any method (atleast simple enough) to send variables dynamically from server to client in an html page. Using a template engine would be the best choice in your use case.
For eg. you are passing user from server side and most probably want the passed variable to be rendered on the client side. You can just install an view engine like ejs - npm install ejs, set your view engine in app.js - app.use('view engine','ejs'); , and just add this line in the html page where you want to send the variable to client side like - <p> <%= user %> </p> and that's it. Keep your html file in view folder and this would do it.
I'm new in SailsJS so i have a question about rendering partial views.
I've came from .NET world and partial views in ASP.NET MVC are much more clever than in sails. In .NET MVC i can provide some controller as partial view path and this controller will be executed and partial view will be rendered with that controller data.
For example I want to show some account info in the corner of my website. So in .NET i can call partial view, providing controller path, this controller will query account info, provide it to partial view, and then this result will be inserted to main view.
In Sails i can call partial view, but all data (locals) for partial view will be pushed there from main view. So i have to put account information in every controller in application?
How can i solve this problem?
In other questions i've found that I can take username from req.session but it does not solve all cases. How can i show three random topics in page footer for example?
I think you are looking at the wrong place about the partial views.
This is a front-end problem .What I use for such partial views is Angular UI-router . Actually I am not sure if using angular is in the scope of the solution for you,So I'll keep this short . If you feel my method is useful ,you can comment it ,and I'll elaborate further on how to do it .
Depends on the template engine, that you use.
With ejs you can use <%- include('someview') %> or <%- include('someview', { mydata: { foo: bar} }) %>
The latter allows the include file to be called several times with diff data. E.g. <%- include('someview', { mydata: foo }) %> will copy foo (from locals) to the mydata key. This will be added to locals, so all other locals are available too.
As for providing the actual data, you can use a sails service. Just add data to res.locals.myKeyForTheInclude.
You will have to call the service each time.
But you can add it in config/http as a middleware.
middleware: {
myFoo: myService.myFunc,
order: [
...
'myFoo', // before router
'router',
...
],
All that is left is that each template needs the include.
You can not avoid that, only the template knows where the include should be.
But if you use a layout, that maybe it fits into the layout.
I have the following folder structure on my Sails.js application:
assets/
myModule/
views/
partials/
Where myModule is a Backbone component (although my client is not a full Backbone application)
There's a given Handlebar partial x.handlebars that need to be rendered both via server and client sides.
My struggle starts when views/ is not accessible on client side so there's no way to load it on Backbone module.
Then I have tried to move it to assets/myModule/templates/ which would be accessible but now my main template views/layout.handlebars can't load that partial if I try something like:
{{> ../assets/myModule/templates/x}}
which doesn't work as well (I assume Handlebars use views/ as root level for the layouts).
There's only two possible solutions I'm seeing in that situation:
Duplicate these layouts and use one on each location (not ideal, but works)
Place it on assets/myModules/templates/x and register a Handlebars partial on Sails to let it available for the server-side rendering.
How could I do that second solution? Is that possible to register a global partial the same way we can do it with the helpers function under config/views.js?
My goal is to use Handlebars.registerPartial function on config level, outside a Controller so that partial could be reused by other templates as well.
Duplicating the code is not necessary. There are many different ways you can implement this and depends on the optimization profile you will be looking for.
A simple solution would be to read the hbs file in the api/controller with node's fs, then compile it with Handlebars and pass it to the template like this:
var rawTemplate = fs.readFileSync('assets/hbs/client-side-template.hbs', "utf8");
var processedTemplate = Handlebars.compile(rawTemplate);
return res.render('whiteboard/dualloadview', {
myPartialAsVariable: processedTemplate({})
});
You'll have have to figure out how to handle the context and variables used by the partials. You can also improve on this code snippet to by looking into keeping the file read in memory, and looking into how to register partials with Handlebars instead of using a variable.
I'm looking to use Express to render raw strings as HTML, with the ability to reference static files in a specified directory (CSS, images, and other resources).
I've done a lot of research, but I haven't seen anything that approaches what I'm trying to do. For example, I thought perhaps writing a custom templating engine that only pretended to load a file would cut it, but that doesn't seem to do the trick.
What's the best way to approach this?
There are many ways to do it.
It can done in any other templating engine as well but here i am guiding you to implement same using EJS(Embedded Javascript).
Use Express Generator to create an ExpressJS app with EJS templating Engine.
command :
express --ejs AppName
For more information about express Generator refer to doc here
Now EJS has tags such as :
1. <% code %> - Code that is evaulated without "echo" it is not printed out.
2. <%= code %> - Code that is evaluated and printed out and escaped!
3. <%- Code %> - Code that is evaluated printed out and not escaped!
So in your case you can use 3rd the third tag that i have mentioned above.
Render EJS views in the usual way from your route config:
res.render('index.ejs', {
// data you want to pass ..
});
Code sample
Some time ago i was playing around with EJS, i developed a very small blogApp for practice.
You can look into this view, line number 33, for more practical way of implementing same.
I need to do the following,
I have a <select> (a list of team names), when the user selects a team, I get relevant information re: the team and display it.
How do I do this in jade?
I'm trying the following, (but I'm wrong obviously, I don't see a lot of documentation out there).
Briefly, I'm doing a include test.jade on my main page, and a res.render('test', {team: team_obj});
jade:
h1 #{team}.name
h2 #{team}.homeGround
h3 #{team}.manager
h4 #{team}.aka
nodejs:
collection.findOne(query, function(err, team_obj){
res.render('test', {team: team_obj});
});
I'm getting the information correctly in team_obj.
Get the following error when I run the app,
team is not defined
Now this is happening because test.jade is getting rendered before I feed it the team_obj.
Questions:
1) Am I doing this right? is include the correct way of partially rendering jade views? if yes, how do I make sure it renders only when the user has selected an option?
2) Is there a partial views concept in jade I'm unaware of?
1) you should use #{team.name}
2) you can't change the team object once the selector is changed. the template was rendered once with the database result. - such functionality should be handled by client side JavaScript and AJAX calls. partials in templates are just a way to share common pieces of templates, and its done in Jade via include.
I don't know what you're rendering and including and when.. but id you use a template variable like #{team.name} you have to make sure that the template was rendered with the team object.