一页上的 Silverstripe 多个用户表单

Silverstripe Multiple Userforms on one page

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

我想我可以创建一个新的页面类型并遍历子项以显示表单,但是 $Form 变量没有呈现表单。

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

我是不是遗漏了什么,或者是否有其他方法可以使用模板文件中的 ID 呈现表单?

您可以尝试以下方法。

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

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

之后您将在循环中调用此函数并将当前 child id 传递给它

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

这应该(代码未经测试)return 您想要的形式。

这里的问题是 DataObject/PageController 之间的区别。遍历 $Children return 是 DataObjectForm 函数和模板变量是 UserDefinedForm 控制器的一部分。

另一个答案显示了一个可行的解决方案,但它上面有一些问题:

  • 将作用域跳转到您的控制器以传递 ID 以获取您的表单
  • 额外的数据库查询
  • 要求所有子页面的类型为 UserDefinedForm

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

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

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;
}

第一部分检查当前对象在其 class 祖先中是否有 UserDefinedForm。如果是,我们然后创建适当的控制器和 return 表单。

您的模板代码应该如下所示:

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

这个解决方案是通用的,原因有以下三个:

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

对于 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;
}