Silverstripe - Is it possible to use a variable in an include statement? - templates

I am using the silverstripe templating and I want to loop through the child pages of the current page and dynamically input the template name in the 'include' control depending on that child's page type.
Here is the code I have so far:
<div id="tertiary-content">
<% if $Children %>
<% loop $Children %>
<% include $ClassName %>
<% end_loop %>
<% end_if %>
</div>
(I have ss files in my templates/Includes directory that relate to the $ClassName variable)
Here's the error I get:
Error was: Unknown open block "loop" encountered. Perhaps you missed the closing tag or have mis-spelled it?
I found this article from a silverstripe forum which makes me think it should work:
http://www.silverstripe.org/archive/show/1023
Is it actually possible to have a variable in an include control?

You could write a function in your Page class that loads a ss template based on the current class name. In your Page.php file.
class Page extends SiteTree {
/**
* Returns a template based on the current ClassName
* #return {mixed} template to be rendered
**/
public function getIncludeTemplate(){
return $this->renderWith($this->ClassName);
}
}
and then in your Template
<div id="tertiary-content">
<% if $Children %>
<% loop $Children %>
$IncludeTemplate
<% end_loop %>
<% end_if %>
</div>

You could call renderWith directly from the template, e.g.:
<div id="tertiary-content">
<% if $Children %>
<% loop $Children %>
$renderWith($ClassName)
<% end_loop %>
<% end_if %>
</div>

Did some test and could not get <% include $ClassName %> to work. But you could work around it with something like:
<% if $ClassName = 'SomeClass' %>
<% include SomeClass %>
<% else_if $ClassName = 'SomeOtherClass' %>
<% include SomeOtherClass %>
<% else %>
<% include DefaultClass %>
<% end_if %>
Not as pretty, but does the job.

Related

Ruby on rails Tutorial Missing partial articles/_form

Hi I have just started using Ruby on rails and have been following the tutorial # http://guides.rubyonrails.org/getting_started.html.
The problem I have got, is with 5.12 Using partials to clean up duplication in views.
I am getting the error ActionView::MissingTemplate in Articles#new.
It is looking for _form.html.erb , which is in the directory /app/views/articles/. So not sure why it cannot find it.
articles controller for new
def new
#article = Article.new
end
articles view for new
<h1>New article</h1>
<%= render 'form' %>
<%= link_to 'Back', articles_path %>
articles view for _form.html.erb
<%= form_for #article do |f| %>
<% if #article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#article.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
< % end %>
Any help would be appreciated, need to know how to solve before going on to next part.
Hi I have got it to work by renaming _form.html.erb to_form as the error is looking for /apps/views/_form. I don't know if this is the correct way to solve the problem, as its says in the tutorial to name the file _form.html.erb.
would this cause issues in future doing it this way?
Check the file name, maybe you copied it wrong
I changed the file name to '_form.erb' and it worked. Still puzzled why the full suffix of 'html.erb' didn't work.

How to show spree product variant images only?

Right now I've the following piece of code, which retrieves all images attached to Spree products.
<% #product.images_by_variant.each do |variant_id,images| %>
<ul class="gallery gallery-<%= variant_id %>" data-variant="<%= variant_id %>">
<% images.each do |image| %>
<li>
<%= image_tag(image.attachment.url(:single)) %>
</li>
<% end %>
</ul>
<% end %>
However, there are also images displayed that represent all variants. I want to hide those.
How can I only show variant (different colors for example) for products?
Cheers!
I found the solution. In the products_controller_decorator.rb, I added the following piece of code to the show method:
variants = #product.variants
if variants.blank?
#variants = #product
elsif variants.length > 1
#variants = variants.reject {|variant| variant.is_master? }
end
In the view I rendered the following partial:
<% if #variants == #product %>
<%= render partial: 'product_single/product_gallery', locals: {variant: #product} %>
<% else %>
<% #variants.each do |variant| %>
<%= render partial: 'product_single/product_gallery', locals: {variant: variant} %>
<% end %>
<% end %>

How do you use Active Record Enum Radio Buttons in a form?

In my app, there is a comment section on articles. I'd like the user to have the ability to comment with 3 different options. To activate this, I am using an Active Record Enum. Please note that the comment sections is nested under the articles.
resources :articles, only: [:index, :show] do
resources :comments
end
Migration:
class AddEnumToCommentModel < ActiveRecord::Migration
def change
add_column :comments, :post_as, :integer, default: 0
end
end
Comment model:
enum post_as: %w(username, oneliner, anonymous)
I attempted to add this to the content view, but lost. I am guessing I also have to do something in my controller but not sure.
Attempted view :
<%= form_for([#article, #comment]) do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<h3>Fill in your comment</h3>
<%= f.label :content %><br>
<%= f.text_area :content %>
</div>
<div class="post_as">
<h3> Choose how you want to post your comment :</h3>
<%= f.input :content, post_as: ???, as: :radio %>
</div>
<br>
<div class="actions">
<%= f.submit %>
</div>
<br>
<% end %>
Rails creates a class method using the pluralized attribute name when you use enum. The method returns a key value pair of strings you've defined and what integers they map to. So, you could do something like this:
<% Comment.post_as.keys.each do |post_as| %>
<%= f.radio_button :post_as, post_as %>
<%= f.label post_as.to_sym %>
<% end %>
There's also collection_radio_buttons, which is more succinct than the other options.
<%= f.collection_radio_buttons :post_as, Comment.post_as, :second, :first %>
Those last two arguments specify how to get the input's value and label text. In your example Comment.post_as produces a hash of enum key names to the underlying integer, so we can grab those using :second for the integer and :first for the name — easy!
Here's what that produces:
<input type="radio" value="0" name="comment[post_as]" id="comment_post_as_0">
<label for="comment_post_as_0">username</label>
# Etc.
You can also customize the HTML by passing a block, which is my preferred way to create enum radio buttons with clickable labels:
<%= f.collection_radio_buttons :post_as, Comment.post_as, :second, :first do |b|
b.label { b.radio_button + b.text }
end %>
An addition to xxyyxx's answer, if you want the labels to be clickable as well:
<% Comment.post_as.keys.each do |post_as| %>
<%= f.radio_button :post_as, post_as %>
<%= f.label "#{:post_as}_#{post_as.parameterize.underscore}", post_as %>
<% end %>
In the view instead of
<%= f.input :content, post_as: ???, as: :radio %>
you could have
<%= f.radio_button(:post_as, "username") %>
<%= label(:post_as, "Username") %>
<%= f.radio_button(:post_as, "oneliner") %>
<%= label(:post_as, "Oneline") %>
<%= f.radio_button(:post_as, "anonymous") %>
<%= label(:post_as, "Anonymous") %>
Source: http://guides.rubyonrails.org/form_helpers.html#radio-buttons

Conditioning based on checkbox status

When a potential User is editing their Profile, they have an option to show/hide some information from public view. I did that with
<div class="field">
<%= f.text_field :contact %>
<%= f.select(:contact_type_id, ContactType.all.map {|l| [l.name, l.id]}) %>
<%= f.check_box :visible %>
<%= f.label :visible, "Vidljivo" %>
<%= f.link_to_remove "Izbriši kontakt" %>
</div>
in a partial that's called in the view like this
<%= f.fields_for :contacts do |l| %>
<%= render 'contacts_form', f: l %>
<% end %>
What I now want is to display on a public profile page only that information that the User marked as visible, and I tried it through a different partial
<div class="field">
<% if :visible == true %>
<%= f.text_field :contact %>
<% end %>
</div>
called from
<%= f.fields_for :contacts do |l| %>
<%= render 'contacts_show', f: l %>
<% end %>
but it doesn't work. I tried tons of variations, but it all came down to guessing the right syntax. How do I display only those entries which visibility is marked as "true"?
Why are you displaying the public profile as a form? If you only want to show the information you can iterate over the contact information of the user where the contact type is visible.
I solved it by using a different approach. In my user controller I defined an instance variable #visible and passed it the array consisting of all database entries that have visible parameter set to true. Then I used #visible.each in the view to print the desired content.

SIlverstripe check page name in .ss file

I want to check – in the template .ss file – the page name or title in order to show a different image. I'd like to do something like that:
<% if $SiteConfig.Title == 'video' %>
<img src="themes/blackcandy/images/image.jpg" />
<% else if $SiteConfig.Title == 'bio' %>
<img src="themes/blackcandy/images/image1.jpg" />
...
...
<% end_if %>
The code above of course doesn't work. How do I do it? Is there a more efficient way of doing it?
Thanks a lot.
Mauro
If you want to check it throu the title use $Title (without the SiteConfig controller)?
<% if $Title == 'video' %>
<img src="themes/blackcandy/images/image.jpg" />
<% else if $Title == 'bio' %>
<img src="themes/blackcandy/images/image1.jpg" />
<% end_if %>
If you want to check PageType use ClassName
<% if ClassName = PageType1 %>
<img src="themes/blackcandy/images/image1.jpg" />
<% end_if %>
If you want to check throu Url use UrlSegment (see Clints answer)
It's best to use URLSegment for this.
<% if URLSegment = video %>
<img src="themes/blackcandy/images/video-image.jpg" />
<% else_if URLSegment = bio %>
<img src="themes/blackcandy/images/bio-image.jpg" />
<% end_if %>
Thanks to banal at: http://www.silverstripe.org/themes-2/show/11325
assuming you're on silverstripe 2.4:
<% control SiteConfig %>
<% if Title = video %>
video
<% else_if Title = bio %>
bio
<% end_if %>
<% end_control %>
note not to put quotes around the values (bio instead of 'bio').
i supposed the following to be valid too:
<% if SiteConfig.Title = bio %>
but for some reason it doesn't work - not sure about this.