一页上的 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
/Page
和 Controller
之间的区别。遍历 $Children
return 是 DataObject
而 Form
函数和模板变量是 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;
}
我正在尝试创建一个页面,该页面将在选项卡式视图中显示多个用户表单。例如基本联系表、请求报价表等。
我想我可以创建一个新的页面类型并遍历子项以显示表单,但是 $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
/Page
和 Controller
之间的区别。遍历 $Children
return 是 DataObject
而 Form
函数和模板变量是 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;
}