如何在Rails 7的create.turbo_stream.erb文件中执行JavaScript代码?
Rails 7 Turbo Stream中执行JavaScript隐藏弹窗的解决方案
问题背景
在Rails 7项目开发评论功能时,Comment控制器的create动作在评论保存成功后返回turbo_stream格式响应。但在create.turbo_stream.erb中直接编写console.log语句或<script>标签无法执行JavaScript代码,需要实现评论创建成功后隐藏弹窗div的需求。
原相关代码
Comment控制器代码:
def create @comment = current_user.comments.new(comment_params) @feed = Feed.find(params[:comment][:feed_id]) @comment.commentable = @feed @parent = params[:comment][:parent] if params[:comment][:parent].present? respond_to do |format| if @comment.save format.turbo_stream format.html { redirect_to feeds_path, notice: "Comment was successfully created." } format.json { render :show, status: :created, location: @comment } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @comment.errors, status: :unprocessable_entity } end end end
原create.turbo_stream.erb代码:
<%if @parent.present?%> <%= turbo_stream.update("feeds-list-parent-#{@parent}", partial: "feeds/feed", locals: { feed: @feed }) %> <%else%> <%= turbo_stream.update("feeds-list-#{@feed.id}", partial: "feeds/feed", locals: { feed: @feed }) %> <%end%> console.log('hi') # 此处无输出,<script>标签也无法生效
解决方案
Turbo Stream不允许在模板中直接写入裸的JavaScript代码或未通过Turbo动作包裹的<script>标签。要执行JS逻辑,需通过turbo_stream.append(或其他Turbo动作)将<script>标签插入到页面的某个元素中,Turbo会自动执行该脚本。
步骤1:在页面中添加脚本承载元素
在application.html.erb的<body>内添加一个隐藏的div,用于承载Turbo插入的脚本:
<div id="turbo-scripts" style="display: none;"></div>
步骤2:修改create.turbo_stream.erb实现弹窗隐藏
在现有Turbo Stream代码后追加脚本逻辑,替换为你的弹窗ID即可实现隐藏:
<%if @parent.present?%> <%= turbo_stream.update("feeds-list-parent-#{@parent}", partial: "feeds/feed", locals: { feed: @feed }) %> <%else%> <%= turbo_stream.update("feeds-list-#{@feed.id}", partial: "feeds/feed", locals: { feed: @feed }) %> <%end%> <%= turbo_stream.append "turbo-scripts" do %> <script> console.log('评论创建成功'); // 替换为你的弹窗实际ID const commentModal = document.getElementById('your-comment-modal-id'); if (commentModal) { commentModal.style.display = 'none'; // 若使用Bootstrap模态框,可改用以下代码: // const modal = bootstrap.Modal.getOrCreateInstance(commentModal); // modal.hide(); } </script> <% end %>
补充方案(Rails 7.1+适用)
若项目使用Rails 7.1及以上版本,可直接使用turbo_stream.invoke调用前端预定义函数,无需插入script标签:
- 在
create.turbo_stream.erb中添加:
<%= turbo_stream.invoke :hide_comment_modal %>
- 在前端JS文件中定义对应函数:
function hideCommentModal() { const commentModal = document.getElementById('your-comment-modal-id'); if (commentModal) commentModal.style.display = 'none'; }
内容的提问来源于stack exchange,提问作者user24471549
相关产品推荐
相关产品推荐

