You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TYPO3扩展:点击事件链接在同容器加载详情而非刷新插件区域

实现TYPO3扩展中事件详情的Ajax无刷新替换

我来帮你搞定这个Ajax无刷新替换的需求,分几个清晰的步骤来实现:

1. 修改前端列表模板(list.html)

首先调整事件链接的行为,阻止默认页面跳转,同时添加JavaScript处理Ajax请求:

<div id="dncalendar-container"></div>
<f:flashMessages />
<div class="tx_tbpartnereventcal">
<f:for each="{events}" as="event">
    <!-- 替换原链接为自定义标签,用data属性存储事件UID -->
    <a href="#" class="event-cont event-link" data-event-uid="{event.uid}">
        <span class="event-title">{event.title}</span>
        <span class="event-date"><f:format.date format="Y-m-d">{event.date}</f:format.date></span><br>
    </a>
</f:for>
</div>
<!--<f:debug>{_all}</f:debug>-->
<f:format.raw>{scriptDates}</f:format.raw>

<script type="text/javascript">
// 获取TYPO3生成的CSRF Token(用于请求合法性验证)
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;

// 监听事件链接点击
document.querySelectorAll('.event-link').forEach(link => {
    link.addEventListener('click', function(e) {
        e.preventDefault(); // 阻止默认页面跳转
        const eventUid = this.dataset.eventUid;
        const container = document.querySelector('.tx_tbpartnereventcal');

        // 发送Ajax请求加载详情
        fetch('{f:uri.action(action: 'show', controller: 'Events', pageType: 123)}', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'X-CSRF-Token': csrfToken
            },
            body: `events=${eventUid}`
        })
        .then(response => response.text())
        .then(html => {
            container.innerHTML = html; // 替换容器内容为详情
        })
        .catch(error => {
            console.error('加载失败:', error);
            container.innerHTML = '<p>事件详情加载失败,请稍后重试。</p>';
        });
    });
});

// 原日历生成脚本保留
// script to generate calendar
</script>

这里的关键细节:

  • 用data-event-uid存储事件ID,避免硬编码URL
  • 引入CSRF Token是TYPO3的安全要求,必须携带
  • 指定pageType:123用来区分Ajax请求,后续会配置这个页面类型

2. 配置TYPO3特殊页面类型

要让showAction返回不带页面布局的纯详情内容,需要在扩展的ext_localconf.php中添加配置:

// 注册页面类型123用于Ajax请求
$GLOBALS['TYPO3_CONF_VARS']['FE']['pageTypeNum'] = array_merge(
    $GLOBALS['TYPO3_CONF_VARS']['FE']['pageTypeNum'],
    [
        123 => 'Ajax Event Content',
    ]
);

// 为该页面类型禁用全局布局和头部代码
$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript'] .= '
[globalVar = GP:type = 123]
    page.config.disableAllHeaderCode = 1
    page.config.disablePrefixComment = 1
    page.config.metaCharset = utf-8
    page.config.xhtml_cleaning = 0
    page.config.admPanel = 0
[global]
';

这样当请求携带type=123参数时,TYPO3只会渲染控制器返回的局部内容,不会包含整个页面框架。

3. 调整控制器与模板

创建详情局部模板

在Resources/Private/Templates/Events/ShowAjax.html中编写纯详情内容:

<div class="event-detail">
    <h2>{events.title}</h2>
    <p><strong>日期:</strong> <f:format.date format="Y-m-d H:i">{events.date}</f:format.date></p>
    <p>{events.description}</p>
    <!-- 可根据需求添加更多字段 -->
    <button class="back-to-list">返回事件列表</button>
</div>

<script>
// 返回列表的Ajax逻辑
document.querySelector('.back-to-list').addEventListener('click', function() {
    fetch('{f:uri.action(action: 'list', controller: 'Events', pageType: 123)}', {
        method: 'GET',
        headers: {
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
        }
    })
    .then(response => response.text())
    .then(html => {
        document.querySelector('.tx_tbpartnereventcal').innerHTML = html;
    });
});
</script>

修改控制器方法

调整showAction,根据页面类型切换模板:

/**
 * action show
 *
 * @param \TBPartnerNet\TbPartnerTerminkalender\Domain\Model\Events $events
 * @return void
 */
public function showAction(\TBPartnerNet\TbPartnerTerminkalender\Domain\Model\Events $events) {
    $this->view->assign('events', $events);
    
    // 判断是否为Ajax请求,切换到局部模板
    if (($this->request->getQueryParams()['type'] ?? 0) === 123) {
        $this->view->setTemplate('ShowAjax');
    }
}

同理,给listAction也添加Ajax适配,创建ListAjax.html(仅保留列表内容),并在listAction中添加模板切换逻辑:

// 在listAction末尾添加
if (($this->request->getQueryParams()['type'] ?? 0) === 123) {
    $this->view->setTemplate('ListAjax');
}

4. 确保CSRF Token正常输出

如果你的根模板中没有自动生成CSRF标签,需要在<head>部分添加:

<f:security.csrfToken />

这个ViewHelper会生成类似<meta name="csrf-token" content="xxx">的标签,供Ajax请求验证使用。

完成以上步骤后,点击事件列表项就会通过Ajax加载详情内容替换列表容器,点击返回按钮又能重新加载列表,全程无页面刷新~

内容的提问来源于stack exchange,提问作者Alex S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:16:26