Update the page URL type
What’s in this topic
This topic describes how to extend the existing UrlInput
component to implement a new link type, or update an existing one, for your module.
Overview
To update a page URL type, you must:
- Create the link class.
- Add the link to the di.xml file.
- Create the component’s JavaScript implementation.
- Create a controller to search the page.
- Create a controller to return the page or array by
cmsPageId
.
Create the link class
Create a .php
file implementing the new link class in the module directory containing the applicable UI component, such as <your-module>/Ui/Component/UrlInput/
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace %your module namespace%;
use Magento\Framework\UrlInterface;
/** Provides configuration for url input with type CMS page */
class Page implements \Magento\Ui\Model\UrlInput\ConfigInterface
{
/**
* @var \Magento\Framework\UrlInterface
*/
private $urlBuilder;
/**
* @param UrlInterface $urlBuilder
*/
public function __construct(UrlInterface $urlBuilder)
{
$this->urlBuilder = $urlBuilder;
}
/**
* {@inheritdoc}
*/
public function getConfig(): array
{
return [
'label' => __('Page'),
'component' => '%link to .js component you will complete in next step%',
'disableLabel' => true,
'filterOptions' => true,
'searchOptions' => true,
'chipsEnabled' => true,
'levelsVisibility' => '1',
'options' => [],
'sortOrder' => 45,
'multiple' => false,
'closeBtn' => true,
'template' => 'ui/grid/filters/elements/ui-select',
'searchUrl' => $this->urlBuilder->getUrl('%path for search controller%'),
'filterPlaceholder' => __('Page Name'),
'isDisplayEmptyPlaceholder' => true,
'emptyOptionsHtml' => __('Start typing to find cms page'),
'missingValuePlaceholder' => __('Cms Page with ID: %s doesn\'t exist'),
'isDisplayMissingValuePlaceholder' => true,
'validationUrl' => $this->urlBuilder->getUrl('%path for validation controller%'),
];
}
}
Add the link to the di.xml
file
Add the link class you just created to the di.xml
file.
1
2
3
4
5
6
7
<type name="Magento\Ui\Model\UrlInput\LinksConfigProvider">
<arguments>
<argument name="linksConfiguration" xsi:type="array">
<item name="page" xsi:type="string">%link to your class%</item>
</argument>
</arguments>
</type>
Create the component’s JavaScript implementation
Create the JavaScript implementation for the applicable UI component in your module-specific directory, such as <your-module>/view/<area>/web/js/form/element/page-ui-select.js
.
<area>
would be adminhtml
, frontend
, or base
depending on where you are applying the component implementation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'Magento_Ui/js/form/element/ui-select',
'jquery',
'underscore'
], function (Select, $, _) {
'use strict';
return Select.extend({
defaults: {
validationUrl: false,
loadedOption: {},
validationLoading: true
},
/** @inheritdoc */
initialize: function () {
this._super();
this.validateInitialValue();
return this;
},
/**
* Validate initial value actually exists
*/
validateInitialValue: function () {
if (!_.isEmpty(this.value())) {
$.ajax({
url: this.validationUrl,
type: 'GET',
dataType: 'json',
context: this,
data: {
cmsPageId: this.value()
},
/** @param {Object} response */
success: function (response) {
if (!_.isEmpty(response)) {
this.options([response]);
this.loadedOption = response;
}
},
/** set empty array if error occurs */
error: function () {
this.options([]);
},
/** stop loader */
complete: function () {
this.validationLoading(false);
this.setCaption();
}
});
} else {
this.validationLoading(false);
}
},
/** @inheritdoc */
getSelected: function () {
var options = this._super();
if (!_.isEmpty(this.loadedOption)) {
return this.value() === this.loadedOption.value ? [this.loadedOption] : options;
}
return options;
},
/**
* Get path to current option
*
* @param {Object} data - option data
* @returns {String} path
*/
getPath: function (data) {
var path = '';
if (this.renderPath) {
path = data.identifier || path;
}
return path;
}
});
});
Create a controller to search the page
Create a controller to search the page using a search key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace %path to your module namespace%;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\UrlInterface;
class Search extends \Magento\Backend\App\Action implements HttpGetActionInterface, HttpPostActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_Cms::save';
/**
* @var \Magento\Framework\Controller\Result\JsonFactory
*/
private $resultJsonFactory;
/**
* @var \Magento\Cms\Model\ResourceModel\Page\CollectionFactory
*/
private $cmsCollectionFactory;
/**
* @param \Magento\Framework\Controller\Result\JsonFactory $resultFactory
* @param \Magento\Cms\Model\ResourceModel\Page\CollectionFactory $cmsCollectionFactory
* @param \Magento\Backend\App\Action\Context $context
*/
public function __construct(
\Magento\Framework\Controller\Result\JsonFactory $resultFactory,
\Magento\Cms\Model\ResourceModel\Page\CollectionFactory $cmsCollectionFactory,
\Magento\Backend\App\Action\Context $context
) {
$this->resultJsonFactory = $resultFactory;
$this->cmsCollectionFactory = $cmsCollectionFactory;
parent::__construct($context);
}
/**
* @return \Magento\Framework\Controller\ResultInterface
*/
public function execute(): \Magento\Framework\Controller\ResultInterface
{
$searchKey = $this->getRequest()->getParam('searchKey');
$pageNum = (int)$this->getRequest()->getParam('page');
$limit = (int)$this->getRequest()->getParam('limit');
/** @var \Magento\Cms\Model\ResourceModel\Page\Collection $cmsCollection */
$cmsCollection = $this->cmsCollectionFactory->create();
$cmsCollection->setCurPage($pageNum)->setPageSize($limit);
$totalValues = $cmsCollection->getSize();
$cmsCollection->addFilter('title', ['in'=> $searchKey]);
$pagesById = [];
/** @var \Magento\Cms\Model\Page $cmsPage */
foreach ($cmsCollection as $cmsPage) {
$cmsId = $cmsPage->getId();
$pagesById[$cmsId] = [
'value' => $cmsId,
'label' => $cmsPage->getTitle(),
'identifier' => sprintf(__('ID: %s'), $cmsId)
];
}
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
$resultJson = $this->resultJsonFactory->create();
return $resultJson->setData([
'options' => $pagesById,
'total' => empty($pagesById) ? 0 : $totalValues
]);
}
}
Create a controller to return the page or array
Create a controller to return the page, or empty array if the option doesn’t exist, by the cmsPageId
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace %path to your module%;
use Magento\Framework\App\Action\HttpGetActionInterface;
class GetSelected extends \Magento\Backend\App\Action implements HttpGetActionInterface
{
/**
* Authorization level of a basic admin session
*
* @see _isAllowed()
*/
const ADMIN_RESOURCE = 'Magento_Cms::save';
/**
* @var \Magento\Framework\Controller\Result\JsonFactory
*/
private $resultJsonFactory;
/**
* @var \Magento\Cms\Model\ResourceModel\Page\CollectionFactory
*/
private $cmsCollectionFactory;
/**
* GetSelected constructor.
* @param \Magento\Framework\Controller\Result\JsonFactory $jsonFactory
* @param \Magento\Cms\Model\ResourceModel\Page\CollectionFactory $cmsCollectionFactory
* @param \Magento\Backend\App\Action\Context $context
*/
public function __construct(
\Magento\Framework\Controller\Result\JsonFactory $jsonFactory,
\Magento\Cms\Model\ResourceModel\Page\CollectionFactory $cmsCollectionFactory,
\Magento\Backend\App\Action\Context $context
) {
$this->resultJsonFactory = $jsonFactory;
$this->cmsCollectionFactory = $cmsCollectionFactory;
parent::__construct($context);
}
/**
* @return \Magento\Framework\Controller\ResultInterface
*/
public function execute() : \Magento\Framework\Controller\ResultInterface
{
$cmsPageId = $this->getRequest()->getParam('cmsPageId');
/** @var \Magento\Cms\Model\ResourceModel\Page\Collection $cmsPageCollection */
$cmsPageCollection = $this->cmsCollectionFactory->create();
$cmsPageCollection->addFilter('page_id', $cmsPageId);
$option = [];
if (!empty($cmsPageCollection->getFirstItem()->getData())) {
$cmsPage = $cmsPageCollection->getFirstItem();
$option = [
'value' => $cmsPageId,
'label' => $cmsPage->getTitle(),
'identifier' => sprintf(__('ID: %s'), $cmsPageId)
];
}
/** @var \Magento\Framework\Controller\Result\Json $resultJson */
$resultJson = $this->resultJsonFactory->create();
return $resultJson->setData($option);
}
}