【问题标题】:Can you render multiple views/same layout from one controller action?您可以通过一个控制器操作渲染多个视图/相同的布局吗?
【发布时间】:2018-08-19 08:33:45
【问题描述】:

重要背景:

我正在构建一个渐进式网络应用程序。例如,new 操作可能包含一系列步骤,其中每个步骤都有一个清晰、离散的页面,专门用于该步骤:

  1. 查找您要订购的商品(一些有用的指南)
  2. 将其带到结帐点(一些有用的指南)
  3. 看看它(一些有用的指南)
  4. 出门时锁门

所有页面共享一个具有一些通用功能的布局(例如,每个步骤上的下一步/后退按钮)。这个想法是页面视图看起来像这样:

<div id="step-1">
<div id="step-2" class="hidden">
<div id="step-3" class="hidden">
<div id="step-4" class="hidden">

每个步骤中都有下一步/后退按钮,其中隐藏/取消隐藏其他页面的 javascript。用户从来不需要提交任何东西,它实际上只是引导用户完成一系列步骤,而无需将他们重定向到多个控制器操作(和单独的视图文件),这会增加加载时间。

我正在尝试找出组织视图代码的策略。对我来说最有意义的是这样的

views
  layouts
    progressive_layout.html.erb
  orders
    new
      step_1.html.erb
      step_2.html.erb
      step_3.html.erb
      step_4.html.erb       

上面的内容对我来说非常干净,我觉得它最容易管理,知道在哪里编辑。对于其他上下文,之前,我只有一个文件,在控制器中,我基本上有大量可笑的实例变量来定义视图文件中的各种内容。那行不通。

问题是,通过单个操作,我如何才能真正渲染它?显然我不能执行以下操作(因为每个操作只能调用一次 render):

def new
  4.times do |i|
    render "orders/new/step_#{i}", layout: "progressive_layout"
  end
end

唯一真正的方法是将多次推送到progressive_layout

<% 4.times do |i| %>
   <!-- generic content -->
   <%= render "orders/new/step_#{i}" %> <!-- partialize the unique content -->
   <!-- generic content -->
<% end %>

但这仍然很笨拙,因为progressive_layout 再次用于可能多于/少于 4 步的其他操作。本质上,我想找到一种非常干净的方法,允许单个操作构建 X 数量的“布局唯一内容”对。

这可能吗?

如果不是,我在想我可能需要做的是让控制器只渲染第一步,然后下一个按钮将 AJAX 提交给另一个控制器操作,该操作会拉动正确的下一步进行渲染。

【问题讨论】:

  • 不不不。从服务器中删除客户端层。为什么人们仍然使用模板???客户端可以完全构建自己的用户端。从你的服务器上卸载所有计算。
  • Wicked 会做你需要的吗?
  • @Darkrum 你能提供一个示例答案吗?
  • @jljohnstone 感谢您的提示!检查出来了!据我所知,wicked的每一步都是新的要求吧?在我的情况下,这些步骤就像......表面,它们只是文本说明,所以我只希望 JS 隐藏/显示每个步骤,而不是实际有一个新请求

标签: javascript ruby-on-rails layout view render


【解决方案1】:

Rails 不允许多次渲染。

views
  layouts
    progressive_layout.html.erb
  orders
    new
      step.html.erb
      _step_1.html.erb
      _step_2.html.erb
      _step_3.html.erb
      _step_4.html.erb


#controller
render "orders/new/step", layout: "progressive_layout"


# In step.html.erb
<% 4.times do |i| %>
   <!-- generic content -->
   <%= render "step_#{i}" %> <!-- partialize the unique content -->
   <!-- generic content -->
<% end %>

更新

您可以从外部传递参数并签入部分。 Doc local variables

# In step.html.erb
<%= render partial: "step_#{i}", locals: {hidden: true} %>

# In _step_1.html.erb
 <div class="<%= hidden ? 'hidden': '' %>">

【讨论】:

  • 问题是这将渲染布局一次,大约是步骤内容的 4 倍。我需要围绕内容的每个步骤进行布局
  • @james 为什么要加载布局 4 次?或者你有编号布局layout: "progressive_layout_#{1}"
  • 每个步骤都有完全相同的布局。但是有一些元素取决于步骤,例如,第一步有&lt;div id="back" class="hidden"&gt;,而第2步没有隐藏类,所以我为每个步骤单独渲染布局以解决细微差别
  • hmmm.... 除非有办法产生这些细微的差异,但我会从布局产生一组渲染文件。但这实际上应该适用于yield, flush: true 对吗?
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多