Silverstripe多个用户表单在一个页面上

时间:2016-01-19 22:17:06

标签: silverstripe

我正在尝试创建一个单页面,该页面将在选项卡式视图中显示多个用户表单。例如基本联系表,请求报价表等。

我以为我可以创建一个新的页面类型并循环遍历子项以显示表单,但$ Form变量不会呈现表单。

<% loop $Children %>
   <div>
     <h2>$Title</h2>
     $Form
   </div>
<% end_loop %>

我在这里遗漏了什么,或者是否有不同的方式在模板文件中使用其ID来呈现表单?

3 个答案:

答案 0 :(得分:4)

您可以尝试以下操作。

在页面持有者控制器中创建一个函数,以从特定子项获取表单(必须是UserDefinedForm页面)。为此,您需要创建此子页面的控制器。

public function ChildForm($pageID) {
  $page = UserDefinedForm::get()->byID($pageID);
  $controller = UserDefinedForm_Controller::create($page);
  return $controller->Form();
}

之后你将在你的循环中调用这个函数并将当前的子id传递给它

<% loop $Children %>
   <div>
     <h2>$Title</h2>
     $Top.ChildForm($ID)
   </div>
<% end_loop %>

这应该(代码未经测试)返回您想要的表单。

答案 1 :(得分:3)

这里的问题是DataObject / PageController之间的差异。循环$Children会返回DataObject,而Form函数和模板变量则是UserDefinedForm控制器的一部分。

另一个答案显示了一个有效的解决方案,但它上面有一些头发:

  • 将范围跳转到您的控制器以传递ID以获取您的表单
  • 其他数据库查询
  • 要求所有子页面都为UserDefinedForm
  • 类型

我们可以实现更通用的解决方案,删除其中的一些元素,使代码更易于维护。

将以下内容添加到Page类(不是控制器):

function getInLoopForm() {
    if (in_array('UserDefinedForm', $this->ClassAncestry)) {
        $controllerName = $this->ClassName . '_Controller';
        $controller = $controllerName::create($this);
        if ($controller->hasMethod('Form')) {
            return $controller->Form();
        }
    }
    return false;
}

第一部分检查当前对象的类祖先是否有UserDefinedForm。如果是,我们然后创建适当的控制器并返回表单。

您的模板代码将如下所示:

<% loop $Children %>
   <div>
     <h2>$Title</h2>
     $InLoopForm
   </div>
<% end_loop %>

此解决方案通用有三个原因:

  • 在我们的getInLoopForm函数中,值“UserDefinedForm”可以替换为任何扩展Page的类。如果你如此倾向,它甚至可以被带到YML值。
  • 对于SilverStripe,页面的控制器名称必须与“{PageClassName} _Controller”匹配,因此我们可以通过动态计算控制器名称来滥用它。这允许您扩展UserDefinedForm及其控制器,我们仍然可以调用正确的函数。
  • 您只需要DataObject访问表单,您不需要自己的控制器。

答案 2 :(得分:0)

对于SS 4,需要进行少量代码更改:

public function getInLoopForm() {
    if (in_array('SilverStripe\UserForms\Model\UserDefinedForm', $this->ClassAncestry)) {
        $controller = UserDefinedFormController::create($this);
        if ($controller->hasMethod('Form')) {
            return $controller->Form();
        }
    }
    return false;
}