内容选择(模态框中)和跨窗口通信
通常需要在编辑其他内容时选择内容值的功能。通常这是通过使用模态窗口来实现的。但是,当模态内容是 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-select
、modal-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'})
;
对话框按钮和高级用法
建议所有交互式按钮(如 save
、cancel
等)都嵌入到对话框内容(iframe 内),而不是由父窗口渲染。这减少了复杂性,并使代码更可靠。
在使用创建/编辑/取消时,控制器通常会重定向到一个完整的页面。对于对话框窗口,您可以重定向到 layout=modalreturn
,并在该页面上将最终状态设置为 scriptOptions
,然后 modal-content-select
脚本将检查它,并将结果发布到父级。示例
$doc->addScriptOptions('content-select-on-load', [
'id' => 1,
'title' => 'A title',
]);