Rails 4: Turbolinks 使用 flash 重定向
Rails 4: Turbolinks redirect with flash
假设我有一个标准控制器创建操作:
def create
@object = Object.new(object_params)
if @object.save
redirect_to @object, flash: {success: "Created object successfully."}
else
render :new
end
end
现在,如果我将重定向更改为使用 turbolinks:
redirect_to @object, turbolinks: true, flash: {success: "Created object successfully."}
服务器 returns 一个 text/javascript 响应,我的浏览器将其显示为白页,上面只有这行文本:
Turbolinks.visit('http:/localhost:3000/objects/1');
如何让我的浏览器实际执行该代码而不是将其显示为文本?
另外,如何让闪现成功消息出现?
这不是对您问题的直接回答。但我建议为此使用不显眼的 JS。您需要先在表单中添加 remote: true
。
def create
@object = Object.new(object_params)
if @object.save
flash.now.success = 'Created object successfully.'
else
flash.now.alert = @object.errors.full_messages.to_sentence
end
render :js
end
创建一个仅包含以下内容的文件create.js.erb:
$('#flash').replaceWith("<%= j render partial: 'layouts/flash' %>");
- 这就是 render :js 将呈现回浏览器的内容,从而执行一个脚本,用新的 flash 消息替换您的 flash 容器(#flash 或您使用的任何 id)
- 此外,请确保您有一个局部视图文件 app/layouts/_flash。html.erb 其中包含您的 Flash HTML 代码。
更新:
如果不使用 Unobtrusive JS。您可以像下面这样渲染部分文件:
def create
@object = Object.new(object_params)
if @object.save
flash.now.success = 'Created object successfully.'
else
flash.now.alert = @object.errors.full_messages.to_sentence
end
render partial: 'layouts/flash'
end
然后在您的 HTML 中嵌入如下内容:
$('#myForm').ajaxForm({
url : '<%= url_for objects_path %>',
type: 'post',
dataType : 'json',
success : function (response) {
$('#flash').replaceWith(response);
}
});
P.S。您可能还对 Wiselinks 感兴趣,它实际上已经这样做了(部分视图加载;您指定要替换的目标容器)。因为目前 turbolinks
还不支持部分加载,它总是加载整个 body。
这就是我最终使用 Turbolinks 和 materialize toasts 解决此问题以获得出色的闪存 UX 的方式:
在我的控制器中:
format.js {
flash[:toast] = 'Created record successfully.'
render :create
}
在create.js.erb中:
Turbolinks.visit("<%= success_path %>");
在我的 _flash.html.erb 部分:
<% flash.each do |type, message| %>
<% if type == "toast" %>
<script id="toast">
$(function() {
Materialize.toast('<%= message %>', 3000);
});
</script>
<% elsif type == "success" %>
...
<% elsif type == "alert" %>
...
<% end %>
<% end %>
假设我有一个标准控制器创建操作:
def create
@object = Object.new(object_params)
if @object.save
redirect_to @object, flash: {success: "Created object successfully."}
else
render :new
end
end
现在,如果我将重定向更改为使用 turbolinks:
redirect_to @object, turbolinks: true, flash: {success: "Created object successfully."}
服务器 returns 一个 text/javascript 响应,我的浏览器将其显示为白页,上面只有这行文本:
Turbolinks.visit('http:/localhost:3000/objects/1');
如何让我的浏览器实际执行该代码而不是将其显示为文本?
另外,如何让闪现成功消息出现?
这不是对您问题的直接回答。但我建议为此使用不显眼的 JS。您需要先在表单中添加 remote: true
。
def create
@object = Object.new(object_params)
if @object.save
flash.now.success = 'Created object successfully.'
else
flash.now.alert = @object.errors.full_messages.to_sentence
end
render :js
end
创建一个仅包含以下内容的文件create.js.erb:
$('#flash').replaceWith("<%= j render partial: 'layouts/flash' %>");
- 这就是 render :js 将呈现回浏览器的内容,从而执行一个脚本,用新的 flash 消息替换您的 flash 容器(#flash 或您使用的任何 id)
- 此外,请确保您有一个局部视图文件 app/layouts/_flash。html.erb 其中包含您的 Flash HTML 代码。
更新:
如果不使用 Unobtrusive JS。您可以像下面这样渲染部分文件:
def create
@object = Object.new(object_params)
if @object.save
flash.now.success = 'Created object successfully.'
else
flash.now.alert = @object.errors.full_messages.to_sentence
end
render partial: 'layouts/flash'
end
然后在您的 HTML 中嵌入如下内容:
$('#myForm').ajaxForm({
url : '<%= url_for objects_path %>',
type: 'post',
dataType : 'json',
success : function (response) {
$('#flash').replaceWith(response);
}
});
P.S。您可能还对 Wiselinks 感兴趣,它实际上已经这样做了(部分视图加载;您指定要替换的目标容器)。因为目前 turbolinks
还不支持部分加载,它总是加载整个 body。
这就是我最终使用 Turbolinks 和 materialize toasts 解决此问题以获得出色的闪存 UX 的方式:
在我的控制器中:
format.js {
flash[:toast] = 'Created record successfully.'
render :create
}
在create.js.erb中:
Turbolinks.visit("<%= success_path %>");
在我的 _flash.html.erb 部分:
<% flash.each do |type, message| %>
<% if type == "toast" %>
<script id="toast">
$(function() {
Materialize.toast('<%= message %>', 3000);
});
</script>
<% elsif type == "success" %>
...
<% elsif type == "alert" %>
...
<% end %>
<% end %>