I have links made like this:
- #glossaries.each do |g|
%a.{ :href => glossary_path(g), data: { 'turbo_frame': :'entry' } }
= g.title
How can I style active link (active glossary) if result of clicking g.title link is rendered in another frame?
I've tried using helper to give a link some class if current path equal requested path, but it is not working. No 'active' class is given to link:
def current_class?(test_path)
return 'active' if request.path == test_path
''
end
When working with frames current path not showing in browser address bar, so I've tried to force it by data-turbo-action" => "advance". With that browser have current path in address bar, but still link do not have 'active' class..
I write this stimulus controller to handle turbo:click event and make a active state to the clicked element. There is an issue when another turbo:click event handler cancelled the visit, but in this place I don't care about it.
import { Controller } from "#hotwired/stimulus";
export default class extends Controller{
static targets = ['link']
static classes = ['active']
initialize(){
this.handleTurboClick = this.handleTurboClick.bind(this)
}
connect(){
this.element.addEventListener('turbo:click', this.handleTurboClick)
}
disconnect(){
this.element.removeEventListener('turbo:click', this.handleTurboClick)
}
handleTurboClick(event){
this.linkTargets.forEach(target => {
if(target == event.target){
target.classList.add(...this._activeClasses)
}else{
target.classList.remove(...this._activeClasses)
}
})
}
get _activeClasses(){
return this.activeClasses.length == 0 ? ['active'] : this.activeClasses
}
}
<div data-controller="turbo-active-link" data-turbo-active-link-active-class="bg-gray-300 hover:bg-gray-300" data-turbo-frame="main">
link A
link B
</div
The reason why it would not update is because the other frame is navigating while the rest of the page stays the same. To make it show the active navigation link you are going to want to either reload both or use some custom JavaScript. I would rather just reload both sides I would do another turbo-frame around the navigation and the sidepanel like so
<%= turbo_frame_tag "glosarries_index" do %>
... Navigation links would be here but remove the data-turbo-frame it will automatically use the closest parent.
<%= turbo_frame_tag "entry" do %>
...
<% end %>
<% end %>
Related
I have an Entry model. I render each entry using a partial. Below each entry, I have a button. Clicking on that button shows the complete entry within a turbo frame.
When the turbo frame loads, the #toggle action is fired in the stimulus controller. Rails generates a unique id for every button using dom_id(entry, :show). (show_entry_1000529641 for example).
I want to reference the button element in the #toggle action.
I understand that the usual way of referencing targets is by first declaring them at the top static targets = [...]. But since the target ids are generated dynamically, I'm not sure what to do.
At the moment, I am setting a data-button attribute on the turbo frame. Then using that value to look up the button element.
I feel like there is probably a better way of doing this. What is the correct/better way?
#entries/_entry.html.erb
#...
<%=
button_to "Show #{entry}",
entry_path(entry),
id: dom_id(entry, :show),
method: :get,
data: { turbo_frame: dom_id(entry) } %>
#...
<%= turbo_frame_tag entry,
data: {
controller: "buttons",
action: "turbo:frame-load->buttons#toggle",
button: dom_id(entry, :show)
} %>
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
toggle() {
const button_id = this.element.getAttribute('data-button')
const button = document.getElementById(button_id)
console.log(button)
}
}
The Targets use a name as a reference, not an ID (see documentation)
The correct Stimulus approach is to have all necessary elements inside the controller and reference these using Target names. The controller <div> acts as a scope therefore you can have multiple same name controllers with same name targets in one page and it would just work, no need for element IDs.
There where you would normally use a reference by ID, use this.exampleTarget in Stimulus. An analogy for a reference by a class is this.exampleTargets. Targets must be defined in the static targets = ['example'] and in the element's data attribute data-controllerName-target="example"
I suggest you try something like this:
#entries/_entry.html.erb
#...
<div data-controller="buttons">
<%=
button_to "Show #{entry}",
entry_path(entry),
id: dom_id(entry, :show),
method: :get,
data: { turbo_frame: dom_id(entry),
buttons_target: 'button'
} %>
#...
<%= turbo_frame_tag entry,
data: {
action: "turbo:frame-load->buttons#toggle",
button: dom_id(entry, :show)
} %>
</div>
import { Controller } from "#hotwired/stimulus"
static targets = ['button']
export default class extends Controller {
toggle() {
console.log(this.buttonTarget)
}
}
I am using cocoon gem to add/remove a record 'on the fly' from a form in rails. Is there a way to hide the remove link which is added on the page using link_to_remove_association if there is only one row/item ?
I would just wrap it in an if block, eg
<% if foos.size > 0 %>
<% link_to "Remove", remove_foo_path(foo) %>
<% end %>
I fixed it. As the rows were being added from JS, controlling the hiding/showing of the remove link had to be handled from JS itself and not rails.
$(document).ready(function() {
$('#container')
.on('cocoon:after-insert', function() {
if($(".fields-row").length > 1){
$(".remove_fields")[0].style.display="block";
}else{
$(".remove_fields")[0].style.display="none";
}
})
.on("cocoon:after-remove", function() {
if($(".fields-row").length == 1){
$(".remove_fields")[0].style.display="none";
}else{
$(".remove_fields")[0].style.display="block";
}
});
});
.remove_fields class is added to the <a> tag automatically when using link_to_remove_association
For some reason .show()/.hide() methods of JQuery were not working, that is why I have used .style.display
Can use FormBuilder index.
HAML:
.nested_fields
%h3 Nested object
- unless f.index == 0
= link_to_remove_association "remove", f
I'm using Ryan Bates gem to create notification of my app for comments, the comments are polymorphic to the Posts that are created,
BEFORE going into the details, here is the Javascript that picks the first argument no matter what the values are, I have no idea why!
$('#notify').bind('DOMNodeInserted DOMNodeRemoved', function(event) {
if (event.type == 'DOMNodeInserted') {
if ( $('#PostOwnerID').val() == $('#CuID').val() ) {
$("#Notification").removeClass("btn btn-primary");
$("#Notification").addClass("btn btn-success");
alert('Eq')
}
else {
alert('Not Equal')
}
}
else {
}
});
And Here is the rest of what I'm doing, starting from Add Comment View create.js.erb >
<% publish_to "/layouts/comments" do %>
$("#<%= #commentable.id %>").empty();
$("#<%= #commentable.id %>").append("<%= escape_javascript(render(:partial => 'comments')) %>");
$("textarea#user_comment_content").val(null);
<% end %>
And for controller to keep the post short I publish back these fields >
PrivatePub.publish_to("/layouts/comments", "$('#notify').append('#{#comment.content}'); $('#CuID').append('#{current_user.id}'); $('#PostOwnerID').append('#{#commentable.user_id}');")
and where in the notification view I have these lines:
<div id="demo" class="collapse in">
<div id="PostOwnerID"></div>
<div id="CuID"></div>
<div id="notify"></div>
<%= subscribe_to "/layouts/comments" %>
</div>
the if else suppose to check if the Post Owner Is the current user or not, if it was the current user, then he/she gets the notification. BUT it's driving me crazy, because it keeps choosing first Argument!
$("#someDiv").bind("DOMSubtreeModified", function() {
alert("tree changed");
});
Is there a JavaScript/jQuery DOM change listener?
This worked, but I realized I was doing it the wrong way, it's too late to manipulate the data in the front end.
How to pass value through link in controller function.
I want to pass below rc value in link so that routes collect it and send to controller.I am new bies in rails.Anyone please help me to solve the problem.
my html.erb .which collect value from text box through jQuery function.
<script type="text/javascript">
var rc=jQuery("#commonid").val();
</script>
<div ><%=link_to "Alert By Region",alerts/filter_alert %></div>
my routes.rb
file which match the link and send to controller
match 'alerts/filter_alert', :controller => 'alerts', :action => 'filter_alert'
my controller
def filter_alert(x)
#message=x
#title = #title + ' - Alerts'
render :site_alerts
end
Javascript things belong to Javascript. You need to manipulate this value dynamically upon visitor's clicking this link.
In Rails' controller side, you can't hard code the method. You need to use params from query string because you won't know what the input is.
# Views
link_to 'Alert By Region', 'alerts/filter_alert', id: 'alert-link'
# Javascript
$('#alert-link').on('click', function() {
var rc = $("#commonid").val();
if rc {
this.attr['href'] += '?rc='+ encodeURI(rc);
return true;
} else {
alert 'input is blank!';
return false;
}
});
# Controller
def filter_alert
rc = params[:rc]
# Then process based on this
end
I have a controller and I need to make a link to my view:
#projeto.atividades.each do |a|
#mapa[:tasks] << {
id:a.id,
name:<%= link_to a.descricao, edit_atividade_path(atividade) %>
}
end
a.descricao = the word that I want to be the link.
edit_atividade_path(atividade) = my view.
What is the syntax?
Please try the following:
#mapa[:tasks] << {
id:a.id,
name: view_context.link_to(a.descricao, edit_atividade_path(atividade))
}
Also a point to remember is that in your controller you don't need the <% or %> scriptlets since its already ruby code.