can I use partials in a for loop in ejs? - for-loop

I'm trying to include partials in a for loop in EJS.
<% let index = 1 %>
<% for (let item in db) { %>
<div class="box unfocused box_<%=index %> ">
<% if (db[item].type === "video") { %>
<%- include ('partials/_video.ejs') %>
<% } else if (db[item].type === "collection") { %>
<%- include ('partials/_collection.ejs') %>
<% } else if (db[item].type === "box") { %>
<%- include ('partials/_box.ejs') %>
<% } %>
</div>
<% index ++ %>
<% } %>
For some reason, the variables defined in the for loop are not being passed down into the partial. For example, _video.ejs looks like this:
<video muted=true autoplay=true loop=true width="250">
<source src="<%=db[item].src%>" type="video/mp4">
</video>
When I run the code, the browser tells me that item is not defined in _video.ejs (item is defined in the for loop).
How to pass item down into the partial?

<%for(let post of posts){%>
<%-include('_post',{post: post}); %>
<%}%>

Related

How to output variable in sinatra without <%=

In Rails, there exist such helper as "concat" to output variables inside <% %> block for erb remplates. Which helper can I use in Sinatra to perform the same action, without using <%= %> block ? I mean, something like
<%
#code
concat "This should be rendered in HTML, not in console"
#code
%>
EDIT
The code in the view is something like this (yep, too much logic, but this is my first app in Ruby):
<% Dir.glob('uploaded/*').select do |entry| %>
<div class="singleFileItem">
<% if File.directory? entry %>
<img src="images/folder.png">
<% else
case entry.to_s.split(".")[1]
when "doc","docx" %>
<img class="pictogram" src='images/word.png'>
<% when "xls","xlsx" %>
<img class="pictogram" src='images/excel.png'>
<% when "pdf" %>
<img class="pictogram" src='images/pdf.png'>
<% when "png", "jpg", "jpeg" %>
<img class="pictogram" class="imageRaw" src="<%= entry.to_s %>">
<% else %>
<% end
end %>
<br>
<span class="subFileText">
<%= entry.to_s.split("/")[1][0..14] %>...
</span>
</div>
<% end %>
Thanks, guys, I have finally found it.
I have extended the app.rb file with
set :erb, :outvar => '#output_buffer'
def concat(text)
#output_buffer << text
end
And it works. Just type in the .erb view
<% concat "Text that should be added to render" %>
And you all done. Hope, this will help to someone with similar question

Tell <%= ... %> not to add a space

I use the following code in a template to render a date:
<% if job.end_month do %>
<%= "#{job.end_month}/" %>
<% end %>
<%= "#{job.end_year}" %>
This results in 3/ 2014 and not in 3/2014. How can I force Phoenix not to add a space after "#{job.end_month}/"?
One solution would be to create an external helper that did this for you:
e.g.
def job_string(%Job{end_month: nil}), do: job.end_year
def job_string(job), do: "#{job.end_month}/#{job.end_year}"
Then just use that in your view:
<%= job_string(job) %>
Alternatively if you don't want to do all that and would prefer a messier sort of look:
<% if job.end_month do %>
<%= "#{job.end_month}/#{job.end_year}" %>
<% else %>
<%= "#{job.end_year}" %>
<% end %>

Add a class to the first child in a loop using Middleman

I am creating a slider for my blog and I want to add a collection of featured items to it, The slider requires that the first child load with the class selected.
How can I do something like if first child do this else do that
Here is what I have so far:
<ul class="cd-hero-slider">
<% blog.articles.select {|a| a.data[:featured] }.each do |article| %>
<li class="selected" style="background-image: url('https://images.unsplash.com/photo-1447014421976-7fec21d26d86?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&s=c82e04e1201234889daab5427f481731')">
<div class="cd-full-width">
<h2><%= link_to article.title, article %></h2>
<p><%= article.summary(250) %></p>
<%= link_to 'Read More', article, :class => 'cd-btn' %>
</div>
</li>
<% end %>
</ul>
Use each_with_index instead of each - this will give you the object but also the position into the array, first being 0:
<% blog.articles.select {|a| a.data[:featured] }.each_with_index do |article, index| %>
<% if index == 0 %>
<li>I'm the first!</li>
<% else %>
<li>Not the first</li>
<% end %>
<% end %>

Do I need an Enumerator for this?

I want to do this:
<div class="menu">
<%- render_menu do |title,path,children| %>
<%= link_to title, path %>
<div class="submenu">
<%= render_menu(children) do |title,path,children| %>
<%= link_to title, path %>
<%= children %>
<%- end %>
</div>
<% end %>
</div>
The method render_menu would look something like this:
def render_menu(children=nil)
children = Paths.roots if children.nil?
children.collect do |child|
[ child.title, child.path, child.children ]
end
end
I'm not sure what the render_menu needs to return to get the three params..
The render_menu will grab the default menu items if no argument is given..
You have to use yield and replace each for collect inside render_menu:
def render_menu(children=nil)
children = Paths.roots if children.nil?
children.each do |child|
yield([child.title, child.path, child.children])
end
end
You should also modify your template to not display the value returned by render_menu:
<div class="submenu">
<% render_menu(children) do |title,path,children| %>
<%= link_to title, path %>
<%= children %>
<% end %>
</div>

Where can I find the default Object.cshtml Editor template?

I need to modify the default editor template for scaffolding but I havent found the Object.cshtml template, where can I find the default razor Object.cshtml Editor template?
The following blog post describes how to customize the editor templates: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html
Basically you have to add a file named Views\Shared\EditorTemplates\Object.cshtml and put all the logic for displaying the object there.
When #marcind says they're compiled in, the templates themselves are not embedded but are rather written in code. For example, EditorFor calls TemplateFor which may call TextAreaExtensions.TextArea or one of many other extensions which generate the code that is ultimately output. This may be because the we have the option of removing the default view engine and using something like nhaml.
The mapping between the template names and the function creating the resulting output can be seen in System.Web.Mvc.Html.TemplateHelpers. See also System.Web.Mvc.Html.DefaultEditorTemplates.
The closest thing that exists right now are the Webforms templates that exist in Mvc3Futures which are available on the aspnet.codeplex.com website. Within it exists an DefaultTemplates\EditorTemplates folder that contains the templates.
Here's the Object.ascx template:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<script runat="server">
bool ShouldShow(ModelMetadata metadata) {
return metadata.ShowForEdit
&& metadata.ModelType != typeof(System.Data.EntityState)
&& !metadata.IsComplexType
&& !ViewData.TemplateInfo.Visited(metadata);
}
</script>
<% if (ViewData.TemplateInfo.TemplateDepth > 1) { %>
<% if (Model == null) { %>
<%= ViewData.ModelMetadata.NullDisplayText %>
<% } else { %>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<% } %>
<% } else { %>
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => ShouldShow(pm))) { %>
<% if (prop.HideSurroundingHtml) { %>
<%= Html.Editor(prop.PropertyName) %>
<% } else { %>
<% if (!String.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString())) { %>
<div class="editor-label"><%= Html.Label(prop.PropertyName) %></div>
<% } %>
<div class="editor-field"><%= Html.Editor(prop.PropertyName) %> <%= Html.ValidationMessage(prop.PropertyName, "*") %></div>
<% } %>
<% } %>
<% } %>

Resources