Rails nested html helper - html

I'm creating a helper in my rails app where I create a navigation link.
Now I want to add an caret to this link so I can get a nice arrow at the end.
My html should look like this:
<li class='dropdown'>
<a class='dropdown-toggle' data-toggle='dropdown' href='#'
Dropdown
<b class='caret'></b>
</a>
Now I got my helpers setup like this:
content_tag(:li, class: 'active dropdown') do
link_to( text, link, class: 'dropdown-toggle' ) do
content_tag(:b, class: 'caret')
end
end
But when I do this I got this error message:
undefined method `stringify_keys' for "/":String
I also want to add some item to my dropdown so I need to nested some more but I don't know how. Is there anybody who could help me and point me in the right direction?
Thanks!

You’re passing a block to link_to so you shouldn’t pass it link text, as shown in the docs. Try this:
content_tag(:li, class: 'active dropdown') do
link_to(link, class: 'dropdown-toggle' ) do
"#{text}#{content_tag(:b, "", class: 'caret')}".html_safe
end
end

Related

How do you write inline Ruby on Rails ternary operators in an HTML tag with white space?

I'm currently running into a problem where I am trying to make a li tag have specific classes based on a Ruby variable by using a ternary operator:
<li class=<%= loc == #ruby_var ? "nav-item active" : "nav-item" %>>
...
</li>
I expect the results to be an li element with both the nav-item and active classes if #ruby_var is true:
<li class="nav-item active">
...
</li>
However, for some reason, I am getting unexpected results where it only sets the class to the first part of the string that is in the ternary operator, and leaves the second part outside of the class tag:
<li class="nav-item" active>
...
</li>
I have tried using more than one space in my "nav-item active" string but any white space seems to make the class only accept the first elem in the string.
What is the proper way to use the ternary operator to set an HTML tag's classes?
You can write it like this
<li class="<%= loc == #ruby_var ? "nav-item active" : "nav-item" %>">
# ...
</li>
Note the " outside of the erb expression.
Or you can use tag helper like this
<%= tag.li, class: ["nav-item", (:active if loc == #ruby_var)] do %>
# ...
<% end %>
I like the second option better because I prefer not to mix HTML and ERB when describing a tag.

Laravel - Add class to any nav-link if its generated url matches the current route

I'm working with Bootsrtap 4 and I'm trying to add the class active to my nav-item elements whenever their nav-link href attribute is the same as the current url.
On the html side, I uesd a basic url generator as shown below:
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="{{ url('/brands') }}" role="button">Brands</a>
</li>
<!-- ... -->
</ul>
And then I used a jQuery method to compare them with the current url:
$('.navbar-nav .nav-item .nav-link').each( () => {
// If the current path and the link url are the same...
if ($(this).attr('href').indexOf(location.pathname) !== 1) {
// ...then add the class 'active' to 'nav-item', its parent
$(this).parent().addClass('active')
}
})
However, I noticed that $(this).attr('href') was undefined, probably because it's a generated url, and therefore nav-item doesn't get the active class.
EDIT: as an example, for now it's a very basic url, without parameter, which looks like this:
http://domain.example/brands
Does anyone know how to solve this problem? Thanks in advance.
I'd recommend you to go another way. Instead of "activating" the link with jQuery, you could easily do it server-side with Laravel:
<ul class="navbar-nav">
<li class="nav-item">
<a class="{{ Request::is('brands*') ? 'nav-link active' : 'nav-link' }}"
href="{{ url('/brands') }}"
role="button">Brands</a>
</li>
<!-- ... -->
</ul>
Explanation:
Laravel uses the template-engine twig for rendering the HTML server-side. Instead of manipulation the DOM client-side, you can easily add an conditional to check for the current request parameters. Laravel gives you nativeliy the possibility to check the request path even with a wildcard.
Your problem is most likely caused by the difference between using () => {} or function () {}
When you use the arrow syntax the prop this is unbound. Meaning that also $(this) will return an empty jQuery object instead of returning the anchor. Any follow up jQuery chaining will return something empty/undefined.
So, changing .each( () => { to .each(function() { will at least fix your undefined problem.
Information about the arrow syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Okay this is what i do generally do in all my laravel projects when it comes to make sidebar or any link "active" on click :-
<li class="nav-item {{ in_array(Route::currentRouteName(),[
'admin.dashboard',
'admin.updates',
])? 'active show' : ''}}">
<i class="typcn typcn-clipboard"></i>Dashboard
<nav class="nav-sub">
Home
</nav>
</li>
Now notice this {{ BladeHelper::sideBar_link_isActive('admin.dashboard') }}
I created dynamic helper function to get the current url and return "active" class
Path : app\Helpers\BladePageHelper
<?php
namespace App\Helpers;
use Route;
class BladePageHelper
{
public static function sideBar_link_isActive($selectedLink){
$currentRouteName = Route::currentRouteName();
if($selectedLink === $currentRouteName){
return 'active';
}else{
return '';
}
}
}
I'm using route name here like
Route::("/","MyController#mymethod")->name("myname")
You can do this with url too.
I hope this helps.
Happy Coding

Add extra class on basis of if ... else statement

In a view, I'm trying to add an additional class specification "active" on basis of the page the user is on. I have:
<li <%= if current_page?(root_path) class="hvr-bottom active" : class="hvr-bottom" %>><a href=<%= root_path %>>Home</a></li>
This generates the error:
syntax error, unexpected keyword_class, expecting keyword_then or ';' or '\n' ...
How should I adjust the code to add the additional class only if a specific page is visited?
Your current ternary statement seems to be missing a ?. Try the following:
<li class=<%= current_page?(root_path) ? "hvr-bottom active" : "hvr-bottom" %>> ... </li>
Hope that helps!

Using html-tags within HTMTL::link_to_route()

In Laravel, how can I use html-tags when linking to a route via HTML::link_to_route()?
Example of what I have:
<li>
{{ HTML::link_to_route( "books_new", "New Book" ) }}
</li>
What I would like to do:
<li>
{{ HTML::link_to_route(
"books_new",
"<span class='icon-book'></span>New Book"
) }}
</li>
I know this is not the answer you want to hear - but you cannot pass html via link_to_route.
The problem is the output from the HTML class is escaped automatically. So if you try to pass this:
{{ HTML::link_to_route('author','<img src="'.URL::base().'assets/images/image.jpg" alt="icon" />')) }}
it comes out like this:
<img src="http://laravel3.dev/assets/images/image.jpg" alt="icon" />
which will just be text on the screen - no image. Instead you need to use URI::to_route('author') and generate the link yourself. So make a helper a like this (not tested):
function link_to_route_image($route, $image)
{
$m = '<a href="'.URL::to_route($route).'">'
. '<img>'.$image.'</img>'
. '</a>';
return $m;
}
How about something like this?
<li>
<span class='icon-book'></span>New Book
</li>
If you're using "Font Awesome", just adding the class to anchor tag as someone mentioned would be fine for most cases because "Icon classes are echoed via CSS :before". You might need a bit of adjustment in CSS; but it might be better in terms of semantic mark-up.
<a href="{{ URL::route('empdelete', array('id' => $employee->id)) }}">
<img src="{{ asset('images/tick-red.jpg') }}" alt="DRC" id="DRCS-logo" /></a>
You can not have HTML markup with HTML::.... (class) , in the documentation they say that anything that is passed as a parameter to the class is escaped with an HTML entity function to make front-end safer!
You can include font awesome or icon into Laravel Blade Template using this code, i already use and work perfect.
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>Edit
If you're using "Font Awesome", just adding the class to anchor tag as someone mentioned would be fine for most cases because "Icon classes are echoed via CSS :before".
So this is working for me:
<li>
{{ HTML::link_to_route( "books_new", "New Book", null, ['class' => 'fa fa-edit'] ) }}
</li>
So far as I know, Laravel doesn't allow you to do that. To me, it seems out of standards.
Rather, apply a class called icon-book to your anchor tag, and then use the class to put the icon inside your anchor as a 'background-image`.
HTML::link_to_route('books_new', 'New Book', array('class' => 'icon-book'))
Alternatively:
Insert the span tag inside the li tag
Assign the icon-book class to the li tag

Rails: Adding an empty tag plus content to link_to

I'm trying to generate a link using the link_to helper that will output the following HTML:
<i class="some_class"></i>Link Name
However the code I'm using to try to accomplish this:
link_to(tag("i", class: options[:icon]) + title, url)
...is outputting:
<i class="some_class">Link Name</i>
Why is it doing this, and how can I fix it? Thanks.
EDIT:
I believe I found the issue.
<i> tags are not self-closable tags in HTML5. Therefore the text after the i is treated as that element's content.
Have you tried using the block format of link_to?
<%= link_to url do %>
<%= tag("i", class: options[:icon]) %>
Link Name
<% end %>
Tweak that to your needs and maybe you'll get what you're looking for.
This is the icon tag helper I use in my applications which I frequently pass as the first argument to link_to, which can either be used to create a icon tag alone, or an icon tag followed by text.
def icon_tag(icon, *args)
options = args.extract_options!
text = args.first || options.delete(:text)
if text.nil?
content_tag :i, "", class: ["icon", "icon-#{icon}"] + options[:class].to_a
else
"#{icon_tag icon} #{text}".html_safe
end
end