使用 Joomla 5 中的 ModalSelect 表单字段类型,可以在开发扩展时使用类别、制造商和搜索在模式窗口中进行过滤,从而简化从数千个产品中查找正确产品的过程。
在与客户合作的过程中,会遇到各种级别的任务:有人需要一个 5-6 页的简单网站。有人需要大量的商品目录或使用 REST API 与第三方系统集成的在线商店。其他人需要非标准功能,但没有可用的流行解决方案。
Joomla 非常适合开发,并允许您创建易于维护的代码。如果需求遵循 CMS 核心,那么它对所有这些情况都有答案。
要完成一个大项目,我们需要将其拆分为更小的任务,我想在本文中讨论解决其中一个任务。
客户已经在 Joomla (JoomShopping) 在线商店的热门组件之一上创建了产品目录。他们可以选择产品的参数,将其放入购物车并进行购买。一切如常。但是,现在您需要添加为产品创建图形布局的功能。例如,您的产品是杯子或 T 恤。在购买之前,您可以去找产品设计师,上传您的徽标或照片,编写文本,然后将此布局附加到在线商店的订单中。付款后,布局直接进入生产,图像和文字将被应用到您的杯子上并发送到地址。
由于此功能的实现非常耗时,因此将其创建为单独的产品设计器组件。并且数据提供程序插件已经创建,允许您使用一个或另一个电子商务组件。
其中一个小的应用任务是在在线商店组件的商品和产品设计器组件中的商品之间创建连接。对于将来处理内容的内容管理者来说,这应该是方便且直观的。因此,仅创建一个文本字段来指示所需产品的 ID 号是不够的。一个网上商店可能只有几十种产品,那么选择一款产品进行交流并不是一件很困难的事情。如果有数千种产品,则按参数搜索和过滤产品的功能就很重要。如果您可以按类别、制造商过滤产品列表,或按名称在数百个其他产品中查找产品,您的工作将变得更快、更轻松。
看视频
此字段与编辑器按钮插件(editors-xtd 组)的工作非常相似,其中用于选择的数据显示在模式窗口中:文章的链接、模块的简短代码等。
在Joomla管理员面板中,有不同的字段需要填充来自其他组件的数据:指定文章、菜单项、联系人、产品等。通常这些字段被设计为选择选项下拉列表,它们可以设计为带有数据列表的输入类型=“文本”,但也有方便的字段显示所需实体的列表,具有过滤、搜索和分页功能。不仅站点内的源(各种组件、插件)可以充当数据源,还可以通过 REST API 提供第三方服务:CRM、交付服务、外部数据库、其他 Joomla 站点等等。
当在菜单项中选择文章(例如“文章 - 单篇文章”、“联系人 - 单个联系人”)或创建菜单项的别名 - “系统链接 - 菜单”时,我们都见过这些字段的作用项目别名”。不过,让我们提醒自己它们是什么样子的。
模态文章选择窗口。
模式单一联系人选择窗口。
让我们仔细看看这些字段 - 它们到底允许您做什么。在内心深处,我们知道该字段的主要工作是获取所选实体的ID并将该ID放入文本字段。但在屏幕上我们看到了其他东西 - 我们看到的不是 ID 号,而是文章或联系人的标题。很好很方便。您不需要记住 ID 为 1452704 的文章的名称。此外,视频清楚地显示,如果该字段已经有值,则会出现“清除”按钮。它会重置字段的值并允许您再次单击“选择”按钮。
在某些情况下,我们有机会在创建菜单项的过程中创建选定类型的实体 - 文章、联系人等
。此按钮的工作原理考虑了 ACL - Joomla 中的访问权限分离。假设您正在构建一个网站并创建一个“联系人”页面。如果您没有一堆结构复杂的公司分支机构,那么这只是“未分类”类别中常见的 Joomla 文章。它已经拥有文本或变量形式的所有联系人。在古代,您必须先创建文章,然后转到菜单项并为其创建菜单项。你现在不必这样做。
如果字段已经有值,那么在某些情况下,可以在创建菜单项的过程中编辑所选实体(文章、菜单项等)。
因此,使用模式窗口中的选择字段,我们可以:
这就是我眼前的情况。但在 Joomla 的深处还有一个奇怪的 urlCheckin 参数,它允许您将选定的值发送到字段中指定的 url。值得注意的是,Joomla 中的这一功能已经逐渐发展了相当长的时间。然而,可以满足您的需求的单独通用字段类型仅出现在 Joomla 5 中。甚至在 Joomla 4 中也没有。
以前,这个构造函数称为 JForm。我假设并非所有读者都拥有 IDE 这样的开发工具 - 开发环境 - PHP Storm 或 VS Code,因此我将尝试提供额外的指导来导航代码库。
在 Joomla 中,逻辑与视图(实际的 HTML 输出)是分离的,因此我们将同时在多个地方对其进行探索。
逻辑是表单类。在 Joomla 5 中,Form 类文件位于 libraries/src/Form 中。我们检查这些文件是为了了解逻辑本身、数据会发生什么以及如何使用它。
简而言之,Form 构造函数接收带有字段描述的 XML。读取数据(字段类型、来自 addfieldprefix 属性的自定义字段类(如果有)等),使用 FormHelper 加载所需的字段类。如果字段有一些过滤输出数据的规则 - 使用 FormRule 类 - 记住 filelist 类型的 Joomla 字段,您可以在其中指定过滤参数并选择,例如仅 php 或仅 css 文件。
Joomla 表单字段类文件 位于libraries/src/Form/Field。温和地说,有很多。这是管理面板的构建材料,有时也是前端的构建材料。
类文件描述了类属性,例如 $type、$layout 以及其他操作所需的属性。大多数字段都有方法 getInput() - 实际上返回字段的 HTML 输出,getLayoutData() - 在将字段发送到渲染之前预处理字段数据,getLabel() - 使用字段标签等。
我们记得字段类继承父 FormField 类。在类文件 libraries/src/Form/FormField.php 中,描述了字段的可能属性,这些属性可以在 XML 描述中使用。他们简要描述了它是什么以及为什么。
子类(继承者)能够使用父类的方法,并在必要时覆盖它。
每个字段类都有一个 HTML 输出。在经典的 MVC 中,视图会立即处理数据输出,但在 Joomla 中还有一个附加层 - 布局,它允许您覆盖布局 - 该 CMS 最重要的功能之一。 核心布局是预计位于站点根目录的 layouts 文件夹 中。它们传递一个 $displayData 数组,其中包含从 getLayoutData() 方法接收到的所有数据。我们在 $layout 类属性中指定要使用的输出布局。
<?php /** * Name of the layout being used to render the field * * @var string * @since 3.7 */ protected $layout = 'joomla.form.field.email';
这种类型的录音很常见。在 Joomla 中,layout 是站点根目录下的布局文件夹中布局文件的以点分隔的路径。 也就是说,条目 $layout = 'joomla.form.field.email' 意味着渲染字段时将使用布局 layouts/joomla/form/field/email.php.
<?php use Joomla\CMS\Layout\LayoutHelper; $displayData = [ 'src' => $this->item->image, 'alt' => $this->item->name, ]; echo LayoutHelper::render( 'joomla.html.image', $displayData );
同样,此示例将使用布局layouts/joomla/html/image.php。可以在网站模板和管理面板的 html 文件夹中覆盖某些布局。
因此,如果我们想确切地看到最终有哪些数据进入布局以及如何显示,请转到布局文件中查看。
现在让我们回到本文的主要任务。
示例对于我们学习很重要(撰写本文时为 Joomla 5.0.1):
在撰写本文时,com_contacts 中的单一联系人模式选择字段尚未转换为通用字段类型一,仅位于(在撰写本文时的 Joomla 5.0.2 中)administrator /components/com_contact/src/Field/Modal/ContactField.php。它直接继承FormField,而不是ModalSelectField。
添加自己的字段的操作算法如下:
<?php /** * Name of the layout being used to render the field * * @var string * @since 3.7 */ protected $layout = 'joomla.form.field.email';
为了清楚 PHP 中发生的一切,您需要首先查看字段输出的布局。它位于文件 layouts/joomla/form/field/modal-select.php 中。事实上,有 2 个输入字段是输出 - 一个可见,另一个不可见。所选文章、联系人或产品的标题以占位符的形式输入到可见字段中 - $valueTitle 参数。第二个是他的 id - $value。如果我们还没有选择任何内容,则该字段中应该有一个短语,例如“选择文章”或“选择产品”。这是一个语言常量,我们将其放入 XML 字段的提示属性中或字段类的 setup() 方法中。
可用于输出布局的所有参数(这意味着可以通过编程方式或在 XML 文件中使用的参数):
<?php /** * Name of the layout being used to render the field * * @var string * @since 3.7 */ protected $layout = 'joomla.form.field.email';
正如您可能已经猜到的那样,字段类位于我的插件中。方法plugins/wtproductbuilder/providerjoomshopping/src/Field/ProductlistField.php。我以单模态文章选择字段为基础,重新设计它以满足我的需求——从 JoomShopping 在线商店选择产品。我们用我们自己的类扩展父 ModalSelectField 类。
我的任务只包括产品选择,编辑和创作不是,所以在文章正文中我们只讨论产品选择。 PHP类很小,我会完整给出并评论。
<?php use Joomla\CMS\Layout\LayoutHelper; $displayData = [ 'src' => $this->item->image, 'alt' => $this->item->name, ]; echo LayoutHelper::render( 'joomla.html.image', $displayData );
另外,引入了 getValueTitle() 方法,该方法在已选择并保存实体的情况下显示所选实体的名称(产品名称、文章标题等)。也就是说,我们去编辑菜单项,我们不触及该字段,但我们希望看到人们可以理解的文章标题/产品名称,而不仅仅是一个id。此方法显示所需的标题。
<field type="productlist" name="product_id" addfieldprefix="Joomla\Plugin\Wtproductbuilder\Providerjoomshopping\Field" label="Field label" hint="Field placeholder" />
在一些需要更复杂功能的字段中 - 多语言关联等 - 字段类中还有其他方法覆盖 FormField 类的基本方法:
在我们的例子中,没有这样的需求,所以我们不使用它们。
单击“选择”按钮时,将打开一个模式 Bootstrap 窗口,其中在
在我的插件中,onAjaxProviderjoomshopping() 方法返回产品列表的 HTML 输出。我们用它们循环遍历数组,拍摄照片、名称和输出。代码通常很长,所以我将发布最重要的片段。
简化循环代码示例:
<?php extract($displayData); /** * Layout variables * ----------------- * @var string $autocomplete Autocomplete attribute for the field. * @var boolean $autofocus Is autofocus enabled? * @var string $class Classes for the input. * @var string $description Description of the field. * @var boolean $disabled Is this field disabled? * @var string $group Group the field belongs to. <fields> section in form XML. * @var boolean $hidden Is this field hidden in the form? * @var string $hint Placeholder for the field. * @var string $id DOM id of the field. * @var string $label Label of the field. * @var string $labelclass Classes to apply to the label. * @var boolean $multiple Does this field support multiple values? * @var string $name Name of the input field. * @var string $onchange Onchange attribute for the field. * @var string $onclick Onclick attribute for the field. * @var string $pattern Pattern (Reg Ex) of value of the form field. * @var boolean $readonly Is this field read only? * @var boolean $repeat Allows extensions to duplicate elements. * @var boolean $required Is this field required? * @var integer $size Size attribute of the input. * @var boolean $spellcheck Spellcheck state for the form field. * @var string $validate Validation rules to apply. * @var string $value Value attribute of the field. * @var string $dataAttribute Miscellaneous data attributes preprocessed for HTML output * @var array $dataAttributes Miscellaneous data attribute for eg, data-* * @var string $valueTitle * @var array $canDo * @var string[] $urls * @var string[] $modalTitles * @var string[] $buttonIcons */
第二个。链接标签代码必须包含我们需要的数据的数据属性。我们在货物输出循环的示例代码中看到了这个片段。
<?php /** * Name of the layout being used to render the field * * @var string * @since 3.7 */ protected $layout = 'joomla.form.field.email';
现在让我们开始使用 JavaScript。在撰写本文的过程中,出现了一些细微差别,使我们能够讨论新旧工作方式。
我们记得在工作的过程中,我们连接了以下js脚本
让我们从我们自己的 javascript 开始。在这里,使用 select-link 类,我们获取所有选择器并将单击事件的侦听器挂在它们上。
<?php use Joomla\CMS\Layout\LayoutHelper; $displayData = [ 'src' => $this->item->image, 'alt' => $this->item->name, ]; echo LayoutHelper::render( 'joomla.html.image', $displayData );
如果 id 和 title 一切都很直观,那么数据对象和 postMessage 对于那些习惯使用 Joomla 的人来说可能并不明显。
之前,在 Joomla 2.5、3.x 甚至 4.x 中,使用了以下方法:在字段输出的布局中,我们使用内联脚本将处理函数挂在窗口上,并从 < ;iframe>我们将其称为 window.parent[functionName]。看看这段代码
<field type="productlist" name="product_id" addfieldprefix="Joomla\Plugin\Wtproductbuilder\Providerjoomshopping\Field" label="Field label" hint="Field placeholder" />
在此形式中,函数名称在文章/联系人/菜单项列表中每个链接的 data-function 属性中指定。函数本身被内联放置,有时将其名称与附加 id 统一起来。例如,"jSelectArticle_".$this->id.
jSelectArticle() 函数或类似函数(我们将使用 jSelectProduct())是文件 modal-fields.min.js 中标准 processModalSelect() 函数的包装器。它依次调用 processModalParent() 函数并在执行后关闭模态窗口。
这个函数需要指定一堆参数才能工作:实体的类型(文章、联系人等)、字段的前缀(实际上是 HTML 字段选择器的 id)、实际的 id和 title - 我们需要的参数等
在一项功能中,所有场合的一切都被收集起来。这就是我们字段中数据的放置位置。
但是,现在,在 Joomla 5 中,不再需要此文件。如果我们使用字段输出的标准布局,那么 modal-content-select-field 资源就会连接到它,以一种新的方式工作。
现在,Joomla 5 前端正在切换为使用 JavaScript postMessages。由于并非所有旧扩展都已准备好切换到新 Rails,因此已实现 JoomlaExpectingPostMessage 标志,它允许您区分过时的事件调用方法。它与所描述的工作方法有间接关系,但可能对某人有用。在完全过渡到 postMessages 后,此标志将被删除。
所以,现在我们不需要带有被调用函数名称的额外链接属性。相反,我们使用 postMessage 机制。为此,在数据对象中,我们需要指定等于 joomla:content-select 的 messageType 参数。为什么?从 JavaScript 的角度来看,在 Joomla 中工作如下:
在研究Joomla核心代码和寻找解决方案的过程中,很自然地遇到了jSelectArticle()之类的函数。然后我遇到了 postMessage 并决定通过给它一个长的唯一名称来创建我的 MessageType。为了使其工作,我编写了自己的处理过程,调用(事实证明,已经过时的)processModalSelect() 函数。我面临的事实是,尽管数据已正确插入到字段中,但模式窗口不想以任何方式关闭。进一步的搜索首先找到了正确的事件类型,然后删除了不必要的脚本并简化了整个代码。
Joomla 为开发人员提供了一套丰富的工具,用于处理第三方来源的数据并从第三方来源获取数据并在代码中使用它。对于开发人员创建自己的扩展时,使用 JForm 字段非常重要,特别是当需要解决超出典型范围的任务时。当然,这样的模式窗口和其中的数据选择是一种相当特殊的情况,但通过这种方式,您既可以覆盖任何其他 JForm 字段,也可以使用自己的 UX 逻辑创建自己的类型。
以上是在 Joomla 中使用模态选择示例创建自定义表单字段类型的详细内容。更多信息请关注PHP中文网其他相关文章!