admin管理员组文章数量:1316974
I have a simple checklist adding functionality, with two different checklists on the page.
Turbo adds the form to the frame, and then i'm trying to set the focus using stimulus.
The trouble is, when submitting the form by hitting return, even though logging the target shows it has found the correct input, it simply sets the focus to the first instance of the controller on the page, instead of the one that just got connected. when submitting the form using the submit button, this works fine.
How can I make it work?
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["name"]
connect() {
console.log('Checklist controller connected');
this.focusInput();
}
focusInput() {
console.log(this.nameTarget)
console.log('set focus')
this.nameTarget.focus()
}
}
The form looks like this:
<div data-controller="checklist" >
<%= simple_form_for trip.checklist_items.new , data: { checklist_target: "form" } do |f| %>
<%= f.input :checklist_type, as: 'hidden', input_html: { value: checklist_type } %>
<%= f.input :trip_id, as: 'hidden', input_html: { value: trip.id } %>
<div class="row">
<div class="col-md-9">
<%= f.input :name, label: false, placeholder: 'E.G Ski Goggles', required: true, input_html: { data: { checklist_target: "name" } } %>
</div>
<div class="col-md-3">
<%= button_tag(type: 'submit', class: 'btn btn-primary btn-full') do %>
Add Item to Checklist <i class='bi bi-arrow-90deg-left icon-rotate-90'></i>
<% end %>
</div>
</div>
<% end %>
</div>
and the turbo stream
<%= turbo_stream.append "checklist_items_frame_#{@checklist_item.checklist_type}" do %>
<%= render partial: "checklist_items/checklist_item" , locals: { checklist_item: @checklist_item, highlight: true } %>
<% end %>
<%= turbo_stream.update "new_checklist_item_#{@checklist_item.checklist_type}" do %>
<%= render "form", trip: @checklist_item.trip, checklist_type: @checklist_item.checklist_type %>
<% end %>
I have a simple checklist adding functionality, with two different checklists on the page.
Turbo adds the form to the frame, and then i'm trying to set the focus using stimulus.
The trouble is, when submitting the form by hitting return, even though logging the target shows it has found the correct input, it simply sets the focus to the first instance of the controller on the page, instead of the one that just got connected. when submitting the form using the submit button, this works fine.
How can I make it work?
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["name"]
connect() {
console.log('Checklist controller connected');
this.focusInput();
}
focusInput() {
console.log(this.nameTarget)
console.log('set focus')
this.nameTarget.focus()
}
}
The form looks like this:
<div data-controller="checklist" >
<%= simple_form_for trip.checklist_items.new , data: { checklist_target: "form" } do |f| %>
<%= f.input :checklist_type, as: 'hidden', input_html: { value: checklist_type } %>
<%= f.input :trip_id, as: 'hidden', input_html: { value: trip.id } %>
<div class="row">
<div class="col-md-9">
<%= f.input :name, label: false, placeholder: 'E.G Ski Goggles', required: true, input_html: { data: { checklist_target: "name" } } %>
</div>
<div class="col-md-3">
<%= button_tag(type: 'submit', class: 'btn btn-primary btn-full') do %>
Add Item to Checklist <i class='bi bi-arrow-90deg-left icon-rotate-90'></i>
<% end %>
</div>
</div>
<% end %>
</div>
and the turbo stream
<%= turbo_stream.append "checklist_items_frame_#{@checklist_item.checklist_type}" do %>
<%= render partial: "checklist_items/checklist_item" , locals: { checklist_item: @checklist_item, highlight: true } %>
<% end %>
<%= turbo_stream.update "new_checklist_item_#{@checklist_item.checklist_type}" do %>
<%= render "form", trip: @checklist_item.trip, checklist_type: @checklist_item.checklist_type %>
<% end %>
Share
Improve this question
edited Jan 30 at 19:53
Alex
30.1k10 gold badges66 silver badges81 bronze badges
asked Jan 29 at 19:39
WillWill
4,7443 gold badges40 silver badges70 bronze badges
2
- can you share your form. – Alex Commented Jan 30 at 8:15
- @Alex - ok added more of the code. thanks for looking – Will Commented Jan 30 at 9:23
2 Answers
Reset to default 1Can confirm that clicking a button sets focus correctly, but hitting Ender from the input focuses the first input. I don't know why it behaves differently, but there is a solution.
Rendering the same form multiple times produces duplicate id
attributes on inputs. Removing these ids or making them unique fixes the issue.
This is a simplified setup:
# app/views/home/_form.html.erb
<div data-controller="checklist">
<%= form_with url: "/" do |f| %>
<%= f.hidden_field :type, value: type %>
<%= f.text_field :name, data: {checklist_target: "name"} %>
<%= f.submit %>
<% end %>
</div>
# app/views/home/create.turbo_stream.erb
<%= turbo_stream.update "new_checklist_item_#{params[:type]}" do %>
<%= render "form", type: params[:type] %>
<% end %>
<%= turbo_stream.after "new_checklist_item_#{params[:type]}" do %>
<div><%= params[:name] %></div>
<% end %>
# app/views/home/index.html.erb
<div id="new_checklist_item_one">
<%= render "form", type: "one" %>
</div>
<div id="new_checklist_item_two">
<%= render "form", type: "two" %>
</div>
<div id="new_checklist_item_three">
<%= render "form", type: "three" %>
</div>
// app/javascript/controllers/checklist_controller.js
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="checklist"
export default class extends Controller {
static targets = ["name"]
nameTargetConnected(target) {
target.focus()
}
}
The fix:
:namespace
- A namespace for your form to ensure uniqueness of id attributes on form elements. The namespace attribute will be prefixed with underscore on the generated HTML id.
https://api.rubyonrails./classes/ActionView/Helpers/FormHelper.html#method-i-form_with
<%= form_with url: "/", namespace: type do |f| %>
same for simple_form
:
<%= simple_form_for trip.checklist_items.new, namespace: checklist_type do |f| %>
Alternatively, you can remove the id
from the input:
<%= f.text_field :name, id: nil, data: {checklist_target: "name"} %>
for simple_form
:
<%= f.input :name,
input_html: {
id: nil,
data: {checklist_target: "name"}
}
%>
Alex's answer is better, but as a workaround this worked too. Set the focus immediately.
connect() {
this.nameTarget.focus()
this.checkFocusTime(1)
...
}
checkFocusTime(time){
setTimeout(() => {
this.focusInputUnlessActive()
}, time);
}
本文标签: ruby on railsStimulus Not Setting focus for newly connected ControllersStack Overflow
版权声明:本文标题:ruby on rails - Stimulus Not Setting focus for newly connected Controllers - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742000674a2410949.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论