步骤 9 添加 Ajax
在本步骤中,我们将 Ajax 添加到 mod_hello,并说明
- 如何将语言字符串传递到 JavaScript 代码,以及
- 如何从 JavaScript 显示系统消息。
源代码可在 mod_hello 步骤 9 中找到。
com_ajax
Joomla 提供了一个组件 com_ajax
(描述 这里),它允许模块的 JavaScript 代码进行 Ajax 调用并获取 Ajax 响应。
com_ajax 文档移至手册后更新上述链接
在 JavaScript 代码中,我们对 index.php?option=com_ajax&module=hello&method=count&format=json
发起 Ajax 调用。URL 参数的解释如下:
- option=com_ajax 表示 Joomla 将此 HTTP 请求路由到 com_ajax 组件。com_ajax 将解释剩余的 URL 参数
- module=hello 我们希望路由到 mod_hello 模块
- method=count com_ajax 将调用模块辅助类的 countAjax() 方法
- format=json 我们希望响应以 JSON 格式
序列图显示了它是如何工作的
com_ajax 接收到结果后,使用 Joomla JsonResponse 类将结果返回到 JavaScript 代码。
JsonResponse 文档移至手册后更新上述链接
mod_hello 变更
为了演示 Ajax 功能,我们将在模块上提供一个按钮,单击该按钮将触发一个 Ajax 请求以获取已登录用户的数量。Ajax 响应将是
- 如果当前用户已登录,则为已登录用户的数量
- 如果当前用户未登录,则为“未授权”错误
我们在 mod_hello 中的代码变更如下:
- 在 tmpl 文件中输出一个按钮,用户可以单击该按钮
- 创建用于执行 Ajax 调用和处理响应的 js
- 在辅助类中创建
countAjax
函数
tmpl 文件变更
以下是更新后的 tmpl 文件
<?php
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
$document = $this->app->getDocument();
$wa = $document->getWebAssetManager();
$wa->getRegistry()->addExtensionRegistryFile('mod_hello');
$wa->useScript('mod_hello.add-suffix');
// Pass the suffix to add down to js
$document->addScriptOptions('vars', ['suffix' => '!']);
$h = $params->get('header', 'h4');
$greeting = "<{$h} class='mod_hello'>{$hello}</{$h}>";
Text::script('MOD_HELLO_AJAX_OK');
Text::script('JLIB_JS_AJAX_ERROR_OTHER');
?>
<?php echo $greeting; ?>
<div>
<p><?php echo Text::_('MOD_HELLO_NUSERS'); ?><span class="mod_hello_nusers"></span></p>
<button class="mod_hello_updateusers"><?php echo Text::_('MOD_HELLO_UPDATE_NUSERS'); ?></button>
</div>
这里我们使用的是 Text::script 函数将语言字符串传递到 JavaScript 代码。
Text::script('MOD_HELLO_AJAX_OK');
将传递语言字符串 'MOD_HELLO_AJAX_OK' 以使其可供 js 代码使用。
然后,我们可以使用以下方法在 JavaScript 中解释此语言字符串
Joomla.Text._('MOD_HELLO_AJAX_OK')
您可以在 media/system/js/core.js 中的 core.js 库中找到 Joomla.text
。
语言字符串 'JLIB_JS_AJAX_ERROR_OTHER' 位于 lib_joomla.ini 语言文件中,它始终由 Joomla 在其初始化期间加载。
JavaScript 变更
为了方便起见,我们将 Ajax 代码添加到 add-suffix.js 中。新增行如下:
const countUsers = (event) => {
const nusers = event.target.parentElement.querySelector('span.mod_hello_nusers');
Joomla.request({
url: 'index.php?option=com_ajax&module=hello&method=count&format=json',
method: 'GET',
onSuccess(data) {
const response = JSON.parse(data);
if (response.success) {
nusers.innerText = response.data;
const confirmation = Joomla.Text._('MOD_HELLO_AJAX_OK').replace('%s', response.data);
Joomla.renderMessages({ 'info': [confirmation] });
} else {
const messages = { 'error': [response.message] };
Joomla.renderMessages(messages);
}
},
onError(xhr) {
Joomla.renderMessages(Joomla.ajaxErrorsMessages(xhr));
const response = JSON.parse(xhr.response);
Joomla.renderMessages({ 'error': [response.message] }, undefined, true);
}
});
};
document.querySelectorAll('.mod_hello_updateusers').forEach(element => {
element.addEventListener('click', countUsers);
});
我们在更新按钮上设置了 onclick 监听器,单击该监听器将触发 Ajax 调用。
Joomla.request
位于 core.js 中,描述 这里。当然,您可以使用您自己的首选方法来发起 Ajax 请求。
Joomla.renderMessages
位于 media/system/js/messages.js 中,用于在 HTML 文档的系统消息区域中显示消息。查看 messages.js 代码了解如何使用它。
由于我们的代码现在依赖于“messages”和“core”,因此我们需要更新 joomla.asset.json。
此外,我们还应更新 JavaScript 版本号,这将确保浏览器缓存的任何 add-suffix.js 代码都被刷新。
{
"$schema": "https://developer.joomla.net.cn/schemas/json-schema/web_assets.json",
"name": "mod_hello",
"version": "1.0.0",
"description": "Joomla Module Tutorial",
"license": "GPL-2.0-or-later",
"assets": [
{
"name": "mod_hello.add-suffix",
"type": "script",
"uri": "mod_hello/add-suffix.js",
"dependencies": [
"jquery", "core", "messages"
],
"version": "1.1.0"
}
]
}
辅助文件变更
当您登录到管理员后台时,Joomla 会显示已登录用户的列表。经过一番调查,您可以发现这是由管理员模块 administrator/modules/mod_logged 输出的,其中包含其辅助文件中的 getList
方法,该方法返回已登录用户的列表。
一种选择是通过调用 \Joomla\Module\Logged\Administrator\Helper\LoggedHelper::getList() 直接使用此代码,但重用像这样的 Joomla 代码风险很大,因为它可能在不同版本之间发生变化。特别是在将模块从旧样式(Joomla 3)更新到包括依赖注入时,getList 函数会从静态函数变为实例函数。
因此,更直接的方法是复制这种方法并使用类似的数据库查询,辅助文件中的新增行如下所示:
use Joomla\Database\DatabaseInterface;
use Joomla\CMS\Language\Text;
...
public function countAjax()
{
$user = Factory::getApplication()->getIdentity();
if ($user->id == 0) {
// not logged on
throw new \Exception(Text::_('JERROR_ALERTNOAUTHOR'));
}
$db = Factory::getContainer()->get(DatabaseInterface::class);
$query = $db->getQuery(true)
->select('COUNT(*)')
->from('#__session AS s')
->where('s.guest = 0');
$db->setQuery($query);
return (string) $db->loadResult();
}
请注意,com_ajax 在模块 Extension 类上使用 $module->getHelper(...)
来查找 Helper 类(如 步骤 8 所述)。因此,您必须在 services/provider.php 文件中设置 HelperFactory,正如我们在依赖注入步骤中所做的那样。
新的语言字符串
; language strings used inside mod_hello
MOD_HELLO_NAME="Joomla Module Tutorial"
MOD_HELLO_DESCRIPTION="Source code for the Joomla module tutorial"
MOD_HELLO_GREETING="Hello "
MOD_HELLO_HEADER_LEVEL="Header level of greeting"
MOD_HELLO_HEADER_LEVEL_3="Header level 3"
MOD_HELLO_HEADER_LEVEL_4="Header level 4"
MOD_HELLO_HEADER_LEVEL_5="Header level 5"
MOD_HELLO_HEADER_LEVEL_6="Header level 6"
MOD_HELLO_NUSERS="Number of logged-on users: "
MOD_HELLO_UPDATE_NUSERS="Update"
MOD_HELLO_AJAX_OK="Ajax response: %s received ok"
清单文件变更
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" client="site" method="upgrade">
<name>MOD_HELLO_NAME</name>
<version>1.0.9</version>
<author>me</author>
<creationDate>today</creationDate>
<description>MOD_HELLO_DESCRIPTION</description>
<namespace path="src">My\Module\Hello</namespace>
<files>
<folder module="mod_hello">services</folder>
<folder>src</folder>
<folder>tmpl</folder>
<folder>language</folder>
</files>
<scriptfile>script.php</scriptfile>
<media destination="mod_hello" folder="media">
<filename>joomla.asset.json</filename>
<folder>js</folder>
</media>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="header"
type="list"
label="MOD_HELLO_HEADER_LEVEL"
>
<option value="h3">MOD_HELLO_HEADER_LEVEL_3</option>
<option value="h4">MOD_HELLO_HEADER_LEVEL_4</option>
<option value="h5">MOD_HELLO_HEADER_LEVEL_5</option>
<option value="h6">MOD_HELLO_HEADER_LEVEL_6</option>
</field>
</fieldset>
</fields>
</config>
</extension>