Ajax 通话期间 TYPO3 Flexform 设置不可用
TYPO3 Flexform Settings not available during Ajax call
对于我的 TYPO3 Extbase 扩展,我想做一些分页。 ajax 电话和其他一切到目前为止都很好。但是,当我在 ajax 调用期间尝试访问 $this->settings
数组时,我总是得到 null
,其中存储了 flexform 前端插件值。该部分如下所示:
$limit = $this->settings['result']['amount'];
$orderType = $this->settings['order']['type'];
$orderFields = $this->settings['additionorder']['fields'];
$formArr = array();
$this->request->hasArgument('offset') ? $offset = $this->request->getArgument('offset') : null;
$forms = $this->formRepository->findFormsChunked(
$orderFields, $orderType, $limit, $offset
);
foreach ($forms as $key => $form) {
$formArr[] = array(
'formUid' => $form->getUid(),
'formName' => $form->getName(),
'formFile' => $form->getFile()->getOriginalResource()->getPublicUrl(),
'formType' => $form->getFormtype()->getUid()
);
}
return json_encode($formArr);
并且 $this->settings 在我的 ajax 调用期间为空,但我无法想象为什么。这些值是否仅在渲染过程中可用,而在 ajax 调用期间不会发生?
感谢您的帮助。
更新
据我所知,flexform 值仅传递给 selected 控制器操作(即 displaycond),如下所示:
<displayCond>FIELD:switchableControllerActions:=:Controller->ajax:AND:FIELD:switchableControllerActions:=:Controller->normal</displayCond>
并在 select 菜单中:
<numIndex index="1">
<numIndex index="0">LLL:EXT:ext_formpool/Resources/Private/Language/locallang.xlf:name</numIndex>
<numIndex index="1">Controller->normal;Controller->ajax</numIndex>
</numIndex>
所以值也应该传递给 ajaxAction?目前他们不可用...
解决方案
不幸的是,如果您使用单独的页面类型进行 ajax 调用,它根本不起作用。 flexform 存储在数据库中,仅在框架加载过程中被解析。您可以通过包含配置管理器来检查这一点,并尝试解析内容对象的 "pi_flexform" 字段。或者你注入 flexformservice,它在 ajax 调用期间也没有加载。您必须使用 eID 机制来实现此目的。
您是否在 ext_tables.php
中声明了您的 flexforms?我通常这样做:
$extensionName = t3lib_div::underscoredToUpperCamelCase($_EXTKEY);
$pluginNames = array('pluginname1','pluginname2','...');
foreach ($pluginNames as $pluginName) {
$pluginSignature = strtolower($extensionName) . '_'.$pluginName;
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist'][$pluginSignature] = 'recursive';
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
t3lib_extMgm::addPiFlexFormValue($pluginSignature, 'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/'.$pluginName.'.xml');
}
为什么不直接在 ajax 调用中解决它,而不是将您的插件呈现为内容对象?
plugin_yourext_ajax = PAGE
plugin_yourext_ajax {
typeNum = 2000
config {
disableAllHeaderCode = 1
xhtml_cleaning = 1
admPanel = 0
additionalHeaders = Content-type: text/plain
no_cache = 1
}
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
pluginName = YourPLugin
extensionName = YourExt
controller = ControllerName
vendorName = Vendor
action = ajax
switchableControllerActions {
YourPlugin {
1 = ajax
}
}
persistence =< plugin.tx_your_ext.persistence
view =< plugin.tx_your_ext.view
update =< plugin.tx_your_ext.update
settings < plugin.tx_your_ext.settings
}
}
这将 bootstrap 您的分机每次通话,而不是页面呈现
我也有这个问题,后来我发现你需要使用 renderObj,它会使用 ContentObjectRenderer class。我需要 f:link 的 Flexform 值到列表模板中的详细信息页面。
所以在我的例子中,我还想要 Ajax 分页。我只是在我自己的新闻扩展的列表视图中使用了默认的 Fluid paginate 小部件。如果客户端没有 javascript 它仍然有效。所以创建炫酷的 Ajax 分页真的很容易!
typeNum 的打字错误:
ajaxPageExt = PAGE
ajaxPageExt {
typeNum = 778
config {
disableAllHeaderCode = 1
disableCharsetHeader = 1
disablePrefixComment = 1
}
10 < styles.content.get
10 {
stdWrap.trim = 1
select {
where = list_type = "jpnews_list"
}
renderObj < tt_content.list.20.jpnews_list
}
}
部分可能javascript:
$('body').on('click', 'div.jpnews-list ul.f3-widget-paginator li a', (function (e) {
e.preventDefault();
paginateToPageURI = $(this).attr('href') + '&type=' + TYPO3pageType;
var parentDivOfNewsList = $(txJpNews).parent();
$(txJpNews).css('opacity', 0.4);
$(parentDivOfNewsList).append(spinnerHTML);
$.ajax({
type: 'POST',
url: paginateToPageURI,
data: $(this).serializeArray(),
success: function (data) {
$(parentDivOfNewsList).html(data);
},
error: function (xhr, thrownError) {
var msg = "<b>Sorry but there was an error, please contact us..</b><br>";
$(parentDivOfNewsList).html(msg + xhr.status + ' ' + thrownError);
}
});
})
我们通过将插件(内容元素)的 uid
添加到 Ajax 请求的 URL 来解决这个问题,然后使用 [=13= 加载 flexform 配置].
在控制器中构建 URL:
$url = $this->uriBuilder->setTargetPageType(1234)->uriFor(
'ajaxAction',
[
'contentUid' => (int) $this->configurationManager->getContentObject()->data['uid']
]
);
通过设置 flexform 设置来初始化控制器操作:
class SomeController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
protected $flexFormService;
protected $flexformSettings = [];
public function injectFlexFormService(\TYPO3\CMS\Extbase\Service\FlexFormService $flexFormService): void
{
$this->flexFormService = $flexFormService;
}
public function initializeAction(): void
{
parent::initializeAction();
if ($this->request->hasArgument('contentUid')) {
$recordUid = (int) $this->request->getArgument('contentUid');
$record = TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('tt_content', $recordUid, 'pi_flexform');
if (!empty($record['pi_flexform'])) {
$this->flexformSettings = $this->flexFormService->convertFlexFormContentToArray($record['pi_flexform']);
}
}
}
public function ajaxAction(): void
{
//access $this->flexformSettings;
}
}
对于我的 TYPO3 Extbase 扩展,我想做一些分页。 ajax 电话和其他一切到目前为止都很好。但是,当我在 ajax 调用期间尝试访问 $this->settings
数组时,我总是得到 null
,其中存储了 flexform 前端插件值。该部分如下所示:
$limit = $this->settings['result']['amount'];
$orderType = $this->settings['order']['type'];
$orderFields = $this->settings['additionorder']['fields'];
$formArr = array();
$this->request->hasArgument('offset') ? $offset = $this->request->getArgument('offset') : null;
$forms = $this->formRepository->findFormsChunked(
$orderFields, $orderType, $limit, $offset
);
foreach ($forms as $key => $form) {
$formArr[] = array(
'formUid' => $form->getUid(),
'formName' => $form->getName(),
'formFile' => $form->getFile()->getOriginalResource()->getPublicUrl(),
'formType' => $form->getFormtype()->getUid()
);
}
return json_encode($formArr);
并且 $this->settings 在我的 ajax 调用期间为空,但我无法想象为什么。这些值是否仅在渲染过程中可用,而在 ajax 调用期间不会发生?
感谢您的帮助。
更新
据我所知,flexform 值仅传递给 selected 控制器操作(即 displaycond),如下所示:
<displayCond>FIELD:switchableControllerActions:=:Controller->ajax:AND:FIELD:switchableControllerActions:=:Controller->normal</displayCond>
并在 select 菜单中:
<numIndex index="1">
<numIndex index="0">LLL:EXT:ext_formpool/Resources/Private/Language/locallang.xlf:name</numIndex>
<numIndex index="1">Controller->normal;Controller->ajax</numIndex>
</numIndex>
所以值也应该传递给 ajaxAction?目前他们不可用...
解决方案
不幸的是,如果您使用单独的页面类型进行 ajax 调用,它根本不起作用。 flexform 存储在数据库中,仅在框架加载过程中被解析。您可以通过包含配置管理器来检查这一点,并尝试解析内容对象的 "pi_flexform" 字段。或者你注入 flexformservice,它在 ajax 调用期间也没有加载。您必须使用 eID 机制来实现此目的。
您是否在 ext_tables.php
中声明了您的 flexforms?我通常这样做:
$extensionName = t3lib_div::underscoredToUpperCamelCase($_EXTKEY);
$pluginNames = array('pluginname1','pluginname2','...');
foreach ($pluginNames as $pluginName) {
$pluginSignature = strtolower($extensionName) . '_'.$pluginName;
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist'][$pluginSignature] = 'recursive';
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
t3lib_extMgm::addPiFlexFormValue($pluginSignature, 'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/'.$pluginName.'.xml');
}
为什么不直接在 ajax 调用中解决它,而不是将您的插件呈现为内容对象?
plugin_yourext_ajax = PAGE
plugin_yourext_ajax {
typeNum = 2000
config {
disableAllHeaderCode = 1
xhtml_cleaning = 1
admPanel = 0
additionalHeaders = Content-type: text/plain
no_cache = 1
}
10 = USER
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
pluginName = YourPLugin
extensionName = YourExt
controller = ControllerName
vendorName = Vendor
action = ajax
switchableControllerActions {
YourPlugin {
1 = ajax
}
}
persistence =< plugin.tx_your_ext.persistence
view =< plugin.tx_your_ext.view
update =< plugin.tx_your_ext.update
settings < plugin.tx_your_ext.settings
}
}
这将 bootstrap 您的分机每次通话,而不是页面呈现
我也有这个问题,后来我发现你需要使用 renderObj,它会使用 ContentObjectRenderer class。我需要 f:link 的 Flexform 值到列表模板中的详细信息页面。
所以在我的例子中,我还想要 Ajax 分页。我只是在我自己的新闻扩展的列表视图中使用了默认的 Fluid paginate 小部件。如果客户端没有 javascript 它仍然有效。所以创建炫酷的 Ajax 分页真的很容易!
typeNum 的打字错误:
ajaxPageExt = PAGE
ajaxPageExt {
typeNum = 778
config {
disableAllHeaderCode = 1
disableCharsetHeader = 1
disablePrefixComment = 1
}
10 < styles.content.get
10 {
stdWrap.trim = 1
select {
where = list_type = "jpnews_list"
}
renderObj < tt_content.list.20.jpnews_list
}
}
部分可能javascript:
$('body').on('click', 'div.jpnews-list ul.f3-widget-paginator li a', (function (e) {
e.preventDefault();
paginateToPageURI = $(this).attr('href') + '&type=' + TYPO3pageType;
var parentDivOfNewsList = $(txJpNews).parent();
$(txJpNews).css('opacity', 0.4);
$(parentDivOfNewsList).append(spinnerHTML);
$.ajax({
type: 'POST',
url: paginateToPageURI,
data: $(this).serializeArray(),
success: function (data) {
$(parentDivOfNewsList).html(data);
},
error: function (xhr, thrownError) {
var msg = "<b>Sorry but there was an error, please contact us..</b><br>";
$(parentDivOfNewsList).html(msg + xhr.status + ' ' + thrownError);
}
});
})
我们通过将插件(内容元素)的 uid
添加到 Ajax 请求的 URL 来解决这个问题,然后使用 [=13= 加载 flexform 配置].
在控制器中构建 URL:
$url = $this->uriBuilder->setTargetPageType(1234)->uriFor(
'ajaxAction',
[
'contentUid' => (int) $this->configurationManager->getContentObject()->data['uid']
]
);
通过设置 flexform 设置来初始化控制器操作:
class SomeController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
protected $flexFormService;
protected $flexformSettings = [];
public function injectFlexFormService(\TYPO3\CMS\Extbase\Service\FlexFormService $flexFormService): void
{
$this->flexFormService = $flexFormService;
}
public function initializeAction(): void
{
parent::initializeAction();
if ($this->request->hasArgument('contentUid')) {
$recordUid = (int) $this->request->getArgument('contentUid');
$record = TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('tt_content', $recordUid, 'pi_flexform');
if (!empty($record['pi_flexform'])) {
$this->flexformSettings = $this->flexFormService->convertFlexFormContentToArray($record['pi_flexform']);
}
}
}
public function ajaxAction(): void
{
//access $this->flexformSettings;
}
}