我熟悉使用Ajax模板更新页面的特定部分,但是如何在执行此操作时使用布局呈现?例如,给定布局:
#foo
= yield :foo
一个简单的视图“show.html.haml”:
= render @bar
和部分:
- content_for :foo
= bar.to_html
... HTML结果将在布局中呈现,我会看到我的条形内容,但是说我想使用Ajax只更新 #foo div。我创建了“show.js.erb”:
$("#foo").html("<% escape_javascript(render(@bar)) %>");
但是结果什么都没有,因为我的_bar部分被渲染但是在布局之外,因此我的:foo内容永远不会被渲染到。如何让JS模板在该布局中呈现?
答案 0 :(得分:3)
我找到了两个答案,但我想知道是否还有更好的方法。 这些答案适用于Rails 3,顺便说一下。
这可能是“更正确”的方式,但不幸的是我的情况不适用,我稍后会解释。
我还没有完全清楚,在JS请求中,查找格式设置为JS 和 HTML。这意味着如果JS模板不存在,控制器将呈现HTML模板。
但是它不会以相同的方式查看HTML布局,这意味着将呈现HTML模板,但是content_for块永远不会被生成,导致空响应。
因此,为了使上面的简单示例能够开箱即用。您将删除“show.js.erb”并在查找路径中添加JS布局(例如“bars.js.erb”),如下所示:
$("#foo").html("<% escape_javascript(yield(:foo)) %>");
通过这种方式,HTML模板被渲染,但在JS布局中,#foo的HTML被替换为响应的新内容。
然而,#1这对我来说不是一个理想的答案。我的应用程序使用了许多嵌套布局,其中大部分非常相似。为了使上面的例子工作,我必须创建许多JS布局,所有这些布局都或多或少地复制了原始HTML布局。浪费时间,而不是干。所以我提出了这个解决方案。
感觉不如#1理想,请告诉我是否有更合适的方法。但这就是我想出来的:
# in bars_controller.rb
def show
# ...
respond_to do |format|
format.js do
lookup_context.update_details(:formats => [:html]) do
@content = render_to_string
end
render
end
end
end
通过这种方式,我暂时将模板查找的mimetype设置为HTML,将内容呈现为变量,然后呈现JS模板:
// show.js.erb
$("#foo").html("<%= escape_javascript(@content) %>");
还有一个复杂因素。在我的嵌套布局设置中,在HTML响应中,布局调用其父级的呈现以继续构建主体,从而导致整个页面。在我的情况下,我希望它只是返回正文内容。因此,虽然我不需要这个解决方案的JS布局,但我需要稍微改变我的布局,如下所示:
-# my_layout.html.haml
-# (given a parent layout that yields to :body)
- content_for :body do
= yield(:foo)
- if request.xhr?
= yield(:body)
- else
= render :file => "layouts/my_parent_layout"
通过这种方式,不会在JS请求上调用父代,只是导致正文(直到嵌套布局堆栈中的这一点)。