跳至主要内容
版本:5.1

内容选择(模态框中)和跨窗口通信

通常需要在编辑其他内容时选择内容值的功能。通常这是通过使用模态窗口来实现的。但是,当模态内容是 iframe 时,会引入与跨窗口通信相关的额外复杂性。

可能很想从 iframe 中直接访问父级 window.parent['field_id'].value='selected value';。这也是 Joomla 过去所采用的方法。这种方法不安全、不可靠,并且通常不适用于多模式字段(如 SubForm 字段)。

更好的方法是使用基于消息的通信:Window: postMessage() 方法,它提供了一种可靠且安全的方式来从子窗口(iframe)传输任何数据到父级。

工作原理:

  • 发起者创建对话框/模态框,并为当前窗口的 message 事件添加侦听器 window.addEventListener('message', ... );
  • 子窗口处理用户选择,并向父级发送包含所选值的消息 window.parent.postMessage();
  • 发起者接收消息,设置值,删除 message 侦听器,并关闭对话框/模态框;

Joomla 提供了 modal-content-selectmodal-content-select-field 资源和 Joomla\CMS\Form\Field\ModalSelectField,可以按原样使用或作为您字段的基础。

modal-content-select-field 资源与 ModalSelect 字段一起加载,在请求时创建对话框,并侦听 message

modal-content-select 资源,一个应该在 iframe 内加载的帮助程序。它将侦听任何具有 data-content-select 属性的元素的点击事件,并将带有 messageType: 'joomla:content-select' 和元素数据集的消息发布到父级。此外,当 scriptOptions 包含 content-select-on-load 值时,帮助程序将在 iframe 加载事件中将此值发布到父级。 “可选”元素的示例

<button data-content-select data-id="1" data-title="Article 1">Select Article 1</button>
<button data-content-select data-id="31" data-title="Article 31">Select Article 31</button>

它不仅限于 id 和标题,可以根据需要进行扩展。

子窗口可以发布以下消息

  • joomla:content-select 用于向父级发布值,例如 window.parent.postMessage({messageType: 'joomla:content-select', id: 1, title: 'A title'});
  • joomla:cancel 取消任何操作,例如 window.parent.postMessage({messageType: 'joomla:cancel'});

对话框按钮和高级用法

建议所有交互式按钮(如 savecancel 等)都嵌入到对话框内容(iframe 内),而不是由父窗口渲染。这减少了复杂性,并使代码更可靠。

在使用创建/编辑/取消时,控制器通常会重定向到一个完整的页面。对于对话框窗口,您可以重定向到 layout=modalreturn,并在该页面上将最终状态设置为 scriptOptions,然后 modal-content-select 脚本将检查它,并将结果发布到父级。示例

$doc->addScriptOptions('content-select-on-load', [
'id' => 1,
'title' => 'A title',
]);