使用Turbolinks渲染相同页面时无法使用闪光灯

时间:2017-04-14 19:23:40

标签: ruby-on-rails turbolinks

我试图在点击更新端点后显示flash消息。我想让用户保持在同一页面并告诉他信息已更新。我启用了turbolink。

以下是我的行动:

def update
    @form = Form.find(params[:id])

    if @form.update(form_params)
      respond_to do |format|
        flash.now[:notice] = "Form updated successfully"
        format.html  { render 'edit' }
        format.js { render 'edit' }
        # format.html  { redirect_to edit_form_path(@form), notice: "Form updated successfully" }
        format.json { render json: {message: "Form updated successfully", form: @form} }
      end
    else
      respond_to do |format|
        format.html { render 'new'}
        format.json { render json: {errors: @form.errors}, status: :unprocessable_entity }
      end    
    end
  end

我已经尝试了flashflash.now都没有产生结果。如果您看到注释掉的行将重定向到同一页面并渲染闪光灯。

这是我打印falsh的方式:

<%= notice %>
<%= flash.notice %>

我已经使用过它们,但似乎没有用。

根据我的观察,我可以看到Turbolinks击中format.js端点。任何人都可以帮我这个吗?

  

修改

这就是我的表单的样子:

<%= form_with(model: @form, method: 'put') do |f| %>
  <!-- name -->
  <div class="field">
    <label class="label">
      From Name
      <sup class="is-danger">*</sup>
    </label>
    <p class="control">
      <%= f.text_field :name, class: "input" %>
    </p>
    <% if @form.errors.any? %>
    <p class="help is-danger">
      Form name <%= @form.errors[:name].first %>
    </p>
    <% end %>
  </div>

  <!-- create button -->
  <div class="control">
    <%= f.submit class: "button is-primary" %>
  </div>
<% end %>

2 个答案:

答案 0 :(得分:1)

使用Rails格式化Ajax

警告:我在手机上无法测试。但这无论如何都应该有效。

要表示您想通过Ajax提交表单,您需要将remote: true放在表单元素上,如下所示:

<%= form_with model: @form, method: 'put', remote: true do |f| %>
 <!-- rest of the form -->
<% end %>

当您点击提交时,您会注意到该页面没有更改,但您的Rails日志仍然显示您已ping通您的控制器。整齐!

接下来,您需要弄清楚如何处理这些数据。这是respond_to的用途。

respond_to将根据控制器的访问方式发送不同的响应。在您的情况下,重要的是format.js,但您始终希望为HTML提供后备。

def update
    @form = Form.find(params[:id])

    if @form.update form_params
      respond_to do |format|
        flash.now[:notice] = "Form updated successfully"
        format.html  { redirect_to <SHOW PATH> }
        format.js # Will automatically look for update.js.erb
        format.json { render json: {message: "Form updated successfully", form: @form} }
      end
    else
      respond_to do |format|
        format.html { render :edit }
        format.json { render json: {errors: @form.errors}, status: :unprocessable_entity }
      end    
    end
  end
end

请注意,我做了一些代码更改。

现在,当您提交表单时,您应该看到没有任何更改,控制器被命中,处理记录,然后Rails将查找update.js.erb。这就是我们下一步要去的地方!

创建该文件后,请填写:

console.log("<%= notice %>");

此时,确认您在提交后可以在控制台中看到闪光灯。

您需要将显示您的Flash消息的HTML抽象为我打算调用_notifications.html.erb的部分内容,并且它将包含以下内容:

<!-- _notifications.html.erb -->

<div id="flash">
  <% if notice.present? %>
    <%= notice %>
  <% end %>
</div>

最后,您必须更换闪光灯的内容。从update.js.erb删除所有内容并尝试此操作:

$('#flash').replaceWith("<%= j(render 'notifications') %>");
// Or
var flash = document.getElementById('flash'),
  flashParent = flash.parentNode;

flashParent.replaceChild("<%= j(render 'notifications') %>", flash);

那就是它!试一试,让我知道它是否有效。

再一次,这是来自我的手机。您可能必须修复一两个语法错误。

More reading

答案 1 :(得分:0)

使用Rails形成Turbolinks

如果Ajax方法存在太大问题,请删除remote: true并尝试:

def update
    @form = Form.find(params[:id])

    if @form.update form_params
      respond_to do |format|
        format.html  { redirect_to <EDIT PATH>, notice: "Form updated successfully" }
        format.json { render json: {message: "Form updated successfully", form: @form} }
      end
    else
      respond_to do |format|
        format.html { render :edit }
        format.json { render json: {errors: @form.errors}, status: :unprocessable_entity }
      end    
    end
  end
end

然后你应该在页面上有flash数据。尝试使用<%= flash.inspect %>进行验证。 Turbolinks应该在这里处理大部分魔术。

缺点是Turbolinks可以在移动设备上给你一些问题。如果你尝试这种方法,我建议调查一下。

就个人而言,我更喜欢Ajax方法。它的工作量稍微多一点,但它可以让你获得更细粒度的控制。