If I have the following directory structure, is it possible to be able to render partials within partials, basically like creating a view setup that is not to dissimilar to react components (that's how I see it anyway)
- server
- views
- partials
- components
component-1.ejs
component-2.ejs
blog.ejs
navbar.ejs
footer.ejs
home.ejs
contact.ejs
So within my home page I have a partial blog.ejs and within that partial I would like to have component-1.ejs
I have tried a variety of permutations but am always faced with the error Error: Could not find the include file
home.ejs
<div class="example">
<% include partials/blog %>
</div>
blog.ejs
<div class="another-example">
<% include components/component-1 %>
</div>
Is this kind of rendering possible with EJS ?
Related
I have around 10 html documents that only differ due to one div. Is there any way to make a header and footer document, and link them together for each html document? I have used EJS in the past, so I would prefer using it. I am using github pages to host my site, so I cannot use any backend.
Yup! These are called partials in EJS, and you insert them with an include function:
<%- include('header') %>
<!-- Main content -->
<%- include('footer') %>
EJS will look for them in the local directory. Any parameters you passed into app.render in your Express route are passed down to partials too.
If you need to re-use partials on the same page with unique data, you can pass them a data object too:
<% msgs.forEach((msg) => { %>
<%- include('msgPartial', { msg: msg }) %>
<% }) %>
I have a single controller that has 2 actions/views and a channel all of which have been scaffolded and pretty much using a default project.
When I load either view I can see that the channel subscribes properly.
I need the subscription to happen only on one of the views. Currently the asset pipeline appears to be compiling everything into a single js file and then serving that js file to every page.
When I scaffolded my channel it created some javascript called channel.js. How can I include channel.js with only specific actions/views?
The asset pipeline indeed compiles everything into a single JS file, so there is no built-in way to limit the execution of certain JavaScript files to specific actions.
There is a way to solve this, however. First, add this helper method to application_helper.rb:
# application_helper.rb
def body_classes(*args)
return (#body_classes || []).join(" ") if args.empty?
#body_classes ||= []
#body_classes += args.map { |klass| klass.to_s.gsub("_", "-") }
#body_classes.uniq!
nil
end
And use it in your layout:
<!-- application.html.erb -->
<body class="<%= body_classes %>">
<!-- ... -->
</body>
With this, you can specify certain body classes in your templates, to be added to the <body> tag:
<!-- your_action.html.erb -->
<%= body_classes :my_custom, :action_class %>
<h1>Your action</h1>
<!-- ... -->
The code above will add the following classes to <body>:
<body class="my-custom action-class">
Finally, you can test for these body classes in your JS code:
// your_action.js
if($("body").hasClass("my-custom")) {
// run code specific to pages with the 'my-custom' class
}
Try going into your controller that holds the method to the view you want to have the javascript incorporated in and write this inside:
def 'the view you want to effect' # This could be "index" for your index.html.erb view
#java = "channel.js"
end
Then in the following file, locate your <%= javascript_include_tag %>
views > layout > application.html.erb
Include this into your tag to load a different javascript file for any view you want with the previous process. (Try it with CSS inside your CSS include tags too.)
<%= javascript_include_tag '#{#java}' %>
Intent
I need to render portion of hmtl into a page.
Problem
The page is being rendered without styling or layout.
I have a page that I need to be in plain html and not jade. But will still be using jade elsewhere.
I followed along to a similar question and that works to direct to an html page. BUT the styles and layout if not being passed in.
My previous page was cases.jade and started like this
extends layout
block content
.row
.twelve.columns
h1 title
Now my new page is cases.html and starts like this
<div class="row">
<div class="twelve columns">
<h1>Before & After Case Gallery</h1>
and is routed to like this
app.get('/cases', function (req, res)
{
res.render('cases.html');
});
and has this above it
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
It seems like in your jade file, you're extending the layout page, so you include all your layout info. But in the HTML version you aren't importing any of the layout information.
I see you're using ejs. Check out layouts, to see what to put into your template:
<% include head %>
<h1>Title</h1>
<p>My page</p>
<% include foot %>
Here you'll want to do something like <%include layout %>, with your layout page stuff in layout.html. The include line will basically copy-paste the file's content into that spot.
I create a page and some parts of it are layout files that are rendered. However I want to render one of these rendered part again with javascript code.
I want to render these part again
<div id="dialog" title="Bookmark Folders" style="resize: both;">
<%=render "layouts/filetree.html.erb"%>
</div>
It render function creates this:
<div id="accordion">
<% #user.folders.each do |f| %> <h3 id="<%= f.folder_name%>" class="folderBar"><b id="folderName"><%= f.folder_name%></b> created <%=distance_of_time_in_words(f.created_at, Time.now)%> before</h3>
<div class="<%= f.folder_name.delete(" ")%>">
<%if f.docs.empty?%>
<b>-No document currently!-</b>
<%else%>
<% f.docs.each do |r|%>
<%= r.title%><br/>
<b><%=r.url%></b><br />
<%= r.snippet%><hr/>
<%end%>
<%end%>
</div>
<%end%>
</div>
Because after some execution there are some changes over "folders", I want to render this part again to see the update.
You shouldn't attempt to render erb with javascript - it's not how it's done (not to mention you'd have to write yourself a erb parser and eventually call the server for data anyway).
If on the other hand, you're asking how to issue the render of some template using Javasript and then replace old content with new one then...
Watch this http://railscasts.com/episodes/205-unobtrusive-javascript,
read this Rails 3 and RJS to get the idea of how to trigger some content updates via javascript.
General idea is
Render the initial full page
Trigger ajax call (either after some time or by manual user request) to do a request to your rails application
Handle that request and respond to it with javascript script (the script content should contain all the functionality and content to replace what you want)
It's possible to share templates between the server and the client. One library that allows for this is called mustache.
But if this is the only case you need it I'd go with the RJS approach as well.
Instead of rendering I did it AJAX way and update it on the page. Thanks for the answers but I did not use any of these.
I am trying to use the EJS gem for templating in rails 3.1. When I require my template in the application.js file
//= require_directory ./templates
The output I get on the client side wraps the template in an anonymous function and namespaces it, but... that's it. This is the generated output I get.
(function() {
this.JST || (this.JST = {});
this.JST["templates/index"] = <article class="item <%=type%>">
<% if (type === "stat") { %>
<h2>
<span>70%</span>
of teens have one or more social network profiles
</h2>
<% } else { %>
<header>
<a href="/posts/<%=id%>">
<h3><%=type%></h3>
<h2><span>- <%=type%></span></h2>
</a>
</header>
<% if (confidential) { %>
<span class="confidential">Confidential</span>
<% } %>
<% if (type === "video" || type === "music") { %>
play
<% } %>
<img src="<%=image%>" alt="" />
<% } %>
</article>;
}).call(this);
I would expect the template to be compiled into a string. That's the experience I've had with Jammit in the past. Do I need to do that manually? Am I missing something?
Thanks in advance,
A
Sprockets wasn't processing your template through EJS because it didn't end in 'ejs'. You need to use an extension ending in ".jst.ejs" with your template files to get them processed in the right order.
Hmm,
Interestingly, installing rails-backbone gem, rather than placing backbone in the app manually, seemed to solve the problem. I also moved the templates into the backbone directory structure. Maybe the ejs gem has some dependency on the backbone gem (unlikely I think)? Or is it something to do with directory nesting levels, or the way asset pipeline includes directories?
Either way, not sure why this is working but it is working none the less. If anyone could serve up an explanation, I'd appreciate it.