rkw / rkw-ajax
Ajax 函数
Requires
- php: >=5.6
- ext-json: *
- masterminds/html5: ^2.0
- typo3/cms-core: ~7.6.0 || ~8.7.0
This package is auto-updated.
Last update: 2024-09-29 05:42:51 UTC
README
它做什么?
它以简单方便的方式为您的扩展添加 AJAX 功能。您无需自己处理 AJAX 请求。只需像往常一样编写您的扩展和模板代码 - rkw_ajax 将负责其他一切。
设置
- 通过 composer 安装扩展
- 在后台激活扩展
- rkw_ajax 的 TypoScript 设置将自动激活
- 现在您需要通过 TypoScript 激活 AJAX-Js
plugin.tx_rkwajax {
settings {
# cat=plugin.tx_rkwbasics//a; type=boolean; label=Include JS for AJAX-API (Version 2)?
includeAjaxApiJs2 = 1
}
}
- 别忘了将您的常规
page
对象继承到txRkwAjaxPage
对象。这应该在完成所有其他设置之后发生,以便两个对象完全相同。
txRkwAjaxPage.10 < page.10
- 您可以通过在浏览器中调用您的网站并附加到 URL 上的
?type=250
来测试您的设置。这应该渲染带有所有内容的网站,但不包含 CSS 或 JavaScript。
http://rkw-kompetenzzentrum.rkw.local/?type=250
用法
基础知识
首先,您必须从 ActionContoller
扩展 AjaxControllerAbstract
。这样,AJAX 功能就添加到您的扩展中。
class YourController extends \RKW\RkwAjax\Controller\AjaxAbstractController
{
[...]
}
现在基本功能可用,我们可以使用它。以下是一个示例来最好地解释这一点。
示例
假设您有一个扩展,它
- 渲染元素列表
- 为此列表提供筛选器
- 提供分页的更多按钮
Fluid 代码可能看起来像这样
<div class="filters">
<select name="filter1">
<option value="1">Value 1</option>
<option value="2">Value 2</option>
</select>
</div>
<div class="list">
<div class="list__inner">
<div class="list__item">
Item 1
</div>
<div class="list__item">
Item 3
</div>
<div class="list__item">
Item 3
</div>
</div>
<div class="button">
<a href="#">More</a>
</div>
</div>
因此,我们可能希望实现以下行为
- 如果用户筛选列表中的项目,则整个列表应通过 AJAX 刷新。
- 如果用户点击更多按钮,则应通过 AJAX 将更多项目添加到列表中。
- 在这两种情况下,应通过 AJAX 更新更多按钮,以便具有正确的页面编号作为参数。
为了实现此行为,我们必须使用 AjaxWrapper-ViewHelper。此 ViewHelper 标记了您要用于 AJAX 的 HTML 中的部分。使用它,您还可以定义应该执行哪些操作。AjaxWrapper-ViewHelper 期望以下参数
- ajaxId:这是您为区分您使用的部分而定义的内部 ID。您无需考虑命名空间。只需确保每个 ID 都是数字,并且在所有模板、部分和布局中只使用一次。
- ajaxAction:在这里,您定义当通过 AJAX 加载时 ViewHelper 标签内的代码将发生什么。如果您将值设置为 "replace",则将替换现有内容;如果您设置为 "append",则将在现有内容的末尾添加;如果您设置为 "prepend",则将在现有内容之前添加。
- ajaxHelper:在这里,您只需设置 AjaxHelper 对象。
首先,让我们看看修改后的代码,然后再尝试解释为什么这样做
<div class="filters">
<form>
<select name="filter1">
<option value="1">Value 1</option>
<option value="2">Value 2</option>
</select>
<button type="submit">Send</button>
<form>
</div>
<rkwAjax:ajaxWrapper ajaxHelper="{ajaxHelper}" ajaxAction="replace" ajaxId="1">
<div class="list">
<rkwAjax:ajaxWrapper ajaxHelper="{ajaxHelper}" ajaxAction="append" ajaxId="2">
<div class="list__inner">
<div class="list__item">
Item 1
</div>
<div class="list__item">
Item 3
</div>
<div class="list__item">
Item 3
</div>
</div>
</rkwAjax:ajaxWrapper>
<rkwAjax:ajaxWrapper ajaxHelper="{ajaxHelper}" ajaxAction="replace" ajaxId="3">
<div class="button">
<a href="#">More</a>
</div>
</rkwAjax:ajaxWrapper>
</div>
</rkwAjax:ajaxWrapper>
这将像以下这样渲染到前端
<div class="filters">
<form>
<select name="filter1">
<option value="1">Value 1</option>
<option value="2">Value 2</option>
</select>
<button type="submit">Send</button>
<form>
</div>
<div class="list" id="773bc02ea02b903280d609bb6a883735afbd7f14-1" data-rkwajax-id="1" data-rkwajax-action="replace">
<div class="list__inner" id="773bc02ea02b903280d609bb6a883735afbd7f14-2" data-rkwajax-id="2" data-rkwajax-action="append">
<div class="list__item">
Item 1
</div>
<div class="list__item">
Item 3
</div>
<div class="list__item">
Item 3
</div>
</div>
<div class="button" id="773bc02ea02b903280d609bb6a883735afbd7f14-3" data-rkwajax-id="3" data-rkwajax-action="replace">
<a href="#">More</a>
</div>
</div>
如你所见,AjaxWrapper-ViewHelpers 将添加一些属性到它们的第一个子元素。注意,这些属性仅添加到一组有效的 HTML 标签中(例如 DIV 和 FORM)。我们做了什么?我们告诉扩展
- 完全刷新具有 ID "773bc02ea02b903280d609bb6a883735afbd7f14-1" 的 DIV 的 innerHTML - 因为:如果用户筛选列表中的项目,则整个列表应通过 AJAX 刷新。
- 向ID为"773bc02ea02b903280d609bb6a883735afbd7f14-2"的DIV的innerHTML中添加项目 - 原因:如果用户点击更多按钮,应通过AJAX向列表添加更多项目。
- 完全刷新ID为"773bc02ea02b903280d609bb6a883735afbd7f14-3"的DIV的innerHTML - 原因:在这两种情况下,应通过AJAX更新更多按钮,以便正确地作为参数传递页面编号。
还需要提供有关何时执行这些操作的信息。这是通过设置links和forms的additionalParams属性来完成的。您可以结合以下参数和您扩展的自定义参数。
additionalParams="{your_stuff: '{key: value}', rkw_ajax: '{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \'2,3\'}'}"
让我们看看这些参数及其作用
- key:只需在这里添加
ajaxHelper.key
。这是一个内部生成的键,用于防止扩展和插件之间的冲突。 - cid:只需在这里添加
ajaxHelper.contentUid
。这是当前内容元素的uid,以便包含flexform设置。 - idl:这是神奇的部分。在这里,您添加一个要通过AJAX更新的Ajax-Ids列表。
让我们将其整合到我们的示例中
<div class="filters">
<f:form noCacheHash="true" action="list" controller="More" extensionName="RkwRelated" pluginName="Morecontent" class="ajax"
additionalParams="{rkw_ajax : '{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \'1\'}'">
<select name="filter1">
<option value="1">Value 1</option>
<option value="2">Value 2</option>
</select>
<button type="submit">Send</button>
</f:form>
</div>
<rkwAjax:ajaxWrapper ajaxHelper="{ajaxHelper}" ajaxAction="replace" ajaxId="1">
<div class="list">
<rkwAjax:ajaxWrapper ajaxHelper="{ajaxHelper}" ajaxAction="append" ajaxId="2">
<div class="list__inner">
<div class="list__item">
Item 1
</div>
<div class="list__item">
Item 3
</div>
<div class="list__item">
Item 3
</div>
</div>
</rkwAjax:ajaxWrapper>
<rkwAjax:ajaxWrapper ajaxHelper="{ajaxHelper}" ajaxAction="replace" ajaxId="3">
<f:link.action action="list" controller="More" extensionName="RkwRelated" pluginName="Morecontent"
class="ajax"
title="<f:translate key='partials.default.more.boxes.more.labelMore' extensionName='RkwRelated' />"
rel="nofollow" target="_blank"
additionalParams="{tx_rkwrelated_morecontent: '{pageNumber: pageNumber, filter: filter}', rkw_ajax : '{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \'2,3\'}'}">
<f:translate key="partials.default.more.boxes.more.labelMore" extensionName="RkwRelated" />
</f:link.action>
</rkwAjax:ajaxWrapper>
</div>
</rkwAjax:ajaxWrapper>
这样,带有参数idl=1
的表单将负责具有id=1
的AjaxWrapper,并在提交时替换第一个DIV的所有innerHTML。因此,如果用户筛选项目,他将获得一个新列表和一个新的更多按钮。
带有参数idl=2,3
的更多链接将在点击时负责具有id=2
和id=3
的AjaxWrapper。对于具有id=2
的AjaxWrapper,新内容将被添加到第一个DIV的innerHTML中(例如,列表的第二页)。对于具有id=3
的AjaxWrapper,按钮本身将被替换为一个新按钮,该按钮现在包含正确的参数来加载第三页。
最后但同样重要的是:别忘了将CSS类ajax
添加到所有旨在触发AJAX事件的所有元素上 ;-)
这就是基本的魔法。
高级使用选项
在提交时
默认情况下,表单始终在"change"时发送。可以通过使用附加类"ajax-submit-only"将此行为更改为"submit"。
<f:form
action="new"
class="ajax ajax-submit-only"
additionalParams="{rkw_ajax: '{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \'1\'}'}"
>
滚动到顶部
要提交后滚动到顶部,请使用类"ajax-scroll-top"。
加载指示器
作为数据属性,您可以指定应使用"grayed out"的ID的容器,该ID使用"data-ajax-indicator-id"。
特殊情况I:在页面加载时执行AJAX调用
要实现此目的,您只需向网站添加一个模板标记。以下示例还检查了登录用户,并且仅在用户登录时才执行AJAX调用。
<template class="ajax" id="tx-rkwregistration-login-info-ajax"></template>
<f:comment><!-- only do an ajax-call if fe-cookie is set. This is to reduce requests to the server--></f:comment>
<script type="text/javascript">
var txRkwRegistrationAjaxUrl = "{f:uri.action(action:'loginInfo', absolute:'1', addQueryString: '1', additionalParams:'{rkw_ajax : \'{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \\\'1\\\'}\'}') -> f:format.raw()}";
if (document.cookie.indexOf('fe_typo_user=') > -1) {
document.getElementById('tx-rkwregistration-login-info-ajax').setAttribute('data-ajax-url', txRkwRegistrationAjaxUrl);
}
</script>
如果您将其与表单结合使用,还可以检查表单是否已提交。这样,只有在表单未提交时才会触发AJAX调用。在此用例中,如果控制器发生错误,还重要使用forward方法,因为forward方法保留POST变量,从而防止进一步的AJAX调用。
<template class="ajax" id="tx-rkwregistration-login-info-ajax"></template>
<f:comment><!-- only do an ajax-call if fe-cookie is set AND the form was not submitted. This is to reduce requests to the server--></f:comment>
<f:if condition="! {ajaxHelper.isPostCall}">
<script type="text/javascript">
var txRkwRegistrationAjaxUrl = "{f:uri.action(action:'loginInfo', absolute:'1', addQueryString: '1', additionalParams:'{rkw_ajax : \'{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \\\'1\\\'}\'}') -> f:format.raw()}";
if (document.cookie.indexOf('fe_typo_user=') > -1) {
document.getElementById('tx-rkwregistration-login-info-ajax').setAttribute('data-ajax-url', txRkwRegistrationAjaxUrl);
}
</script>
</f:if>
特殊情况II:仅在特定视口中在页面加载时执行AJAX调用
在某些情况下,将AJAX请求绑定到页面加载时的特定视口(例如,仅在移动设备上触发)可能会有所帮助。为了实现这一点,您可以简单地添加相应的属性data-ajax-max-width
。
<template class="ajax" data-ajax-max-width="1280" data-ajax-url="{f:uri.action(action:'mobileMenu', absolute:'1', additionalParams:'{rkw_ajax : \'{key: ajaxHelper.key, cid: ajaxHelper.contentUid, idl: \\\'1\\\'}\'}') -> f:format.raw()}"></template>
其他提示
从版本v8.7.57-stable开始,所有请求都作为"POST"发送,以避免JS错误"HTTP错误414.请求URL太长"。