2

I'm new to Magento 2 and I'm trying to add a multiselect of all (for now) CMS pages to the CMS pages in Magento 2. What I mean by this is that when creating/editing a CMS page, there should be an extra field with all (other) CMS pages from which you can select multiple (or just one or none at all), just like you have a multiselect for the Store View field. I have got it to work to render the multiselect and you can select multiple, but upon saving it shows a message that "something" went wrong. Example of the fields: CMS page multiselect

I've also created an upgrade script which has successfully created an extra field in the cms_page table. I can still save pages, but only when I don't select any CMS pages.

Here's my //view/adminhtml/ui_component/cms_page_form.xml

<?xml version="1.0" encoding="UTF-8"?> <form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <fieldset name="search_engine_optimisation"> <field name="redirect_to"> <argument name="data" xsi:type="array"> <item name="options" xsi:type="object">Magento\Cms\Model\Config\Source\Page</item> <item name="config" xsi:type="array"> <item name="dataType" xsi:type="string">int</item> <item name="label" xsi:type="string" translate="true">Redirect to pages</item> <item name="formElement" xsi:type="string">multiselect</item> <item name="source" xsi:type="string">page</item> <item name="dataScope" xsi:type="string">redirect_to</item> <item name="default" xsi:type="string">0</item> <item name="validation" xsi:type="array"> <item name="required-entry" xsi:type="boolean">false</item> </item> </item> </argument> </field> </fieldset> </form> 

What am I missing or doing wrong? For some reason, I've gotten it to work but it would only save one, never multiple, but I can't seem to reproduce that anymore.

What I'd like to achieve is for it to save all selected options as a JSON encoded string with the store id as key and the URL as value. How would I go about doing this?

Any help is much appreciated.

1 Answer 1

1

First of all you need to change option class for your requirement. So make following way.

Change <item name="options" xsi:type="object">Magento\Cms\Model\Config\Source\Page</item>

to

<item name="options" xsi:type="object">VendorName\ModuleName\Model\Config\Source\Page</item>

 namespace VendorName\ModuleName\Model\Config\Source; class Page extends \Magento\Cms\Model\Config\Source\Page { /** * To option array * * @return array */ public function toOptionArray() { if (!$this->options) { $emptyOption[] = [ 'value' => 'all', 'label' => 'All' ]; $this->options = $this->collectionFactory->create()->toOptionIdArray(); $this->options = array_merge($emptyOption, $this->options); } return $this->options; } } 

Now you can able to see 'All' option inside multiselect element.

For save:

Create a plugin for this: VendorName/ModuleName/etc/adminhtml/di.xml

 <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Cms\Controller\Adminhtml\Page\PostDataProcessor"> <plugin name="PostDataProcessor_Save" type="VendorName\ModuleName\Plugin\Controller\Adminhtml\Page\PostDataProcessor" sortOrder="1"/> </type> <type name="Magento\Cms\Model\Page\DataProvider"> <plugin name="DataProvider_Load" type="VendorName\ModuleName\Plugin\Model\Page\DataProvider" sortOrder="1"/> </type> </config> 

VendorName/ModuleName/Plugin/Controller/Adminhtml/Page/PostDataProcessor.php

 namespace VendorName\ModuleName\Plugin\Controller\Adminhtml\Page; class PostDataProcessor { public function aroundFilter( \Magento\Cms\Controller\Adminhtml\Page\PostDataProcessor $subject, \Closure $proceed, $data ) { if(isset($data['redirect_to']) && ($data['redirect_to'])) { $data['redirect_to'] = json_encode($data['redirect_to']); } return $proceed($data); } } 

For edit:

VendorName/ModuleName/Plugin/Model/Page/DataProvider.php

 namespace VendorName\ModuleName\Plugin\Model\Page; class DataProvider { /** * Get data * * @return array */ public function afterGetData( \Magento\Cms\Model\Page\DataProvider $subject, $result ) { if (is_array($result)) { foreach ($result as &$item) { if(isset($item['redirect_to']) && ($item['redirect_to'])) { $item['redirect_to'] = json_decode($item['redirect_to']); } } } return $result; } } 
3
  • this works great for editing already existing CMS pages, but when I want to create a new CMS page, it throws the following error: Commented Sep 15, 2017 at 7:50
  • Check updated answer. Commented Sep 15, 2017 at 8:01
  • Sorry about the previous comment, it got cut of, here's the full comment: This works great for editing already existing CMS pages, but when I want to create a new CMS page, it throws the following error: Warning: Invalid argument supplied for foreach() in /var/www/app/code/Phpro/CmsRedirect/Plugin/Model/Page/DataProvider.php on line 25. It looks like somethiing was wrong wit the foreach ($result as &$item) {. To circumvent this I wrote a check around that to check if there is a $result and now it works great. Many, many thanks for the quick and elaborate response! Commented Sep 15, 2017 at 8:47

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.