Puede darse el caso en el que querramos incluir un selector de tienda múltiple a través de nuestro componente UI de generación de formulario en Magento.
Esto será útil si queremos mostrar el registro en una u otra tienda.
Lo primero de todo es crear un nuevo campo texto llamado store_id en la tabla que deseamos incluirlo.
El siguiente paso es editar nuestro componente UI que se encarga de generar nuestro formulario e incluiremos un nuevo campo. Nuestro componente UI estará en view/adminhtml/ui_component/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<field name="store_id"> <argument name="data" xsi:type="array"> <item name="options" xsi:type="object">Magento\Cms\Ui\Component\Listing\Column\Cms\Options</item> <item name="config" xsi:type="array"> <item name="dataType" xsi:type="string">int</item> <item name="label" xsi:type="string" translate="true">Store View</item> <item name="formElement" xsi:type="string">multiselect</item> <item name="source" xsi:type="string">news</item> <item name="dataScope" xsi:type="string">store_id</item> <item name="default" xsi:type="string">0</item> <item name="validation" xsi:type="array"> <item name="required-entry" xsi:type="boolean">true</item> </item> </item> </argument> </field> |
A continuación editaremos el ResourceModel de nuestra tabla (en mi caso noticias) y le indicaremos que nuestro campo store_id será serializable ya que nuestro select es múltiple. Reemplaza <vendor>, <module>, el nombre de tabla y la primary key por los de tu tabla.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace <vendor>\<module>\Model\ResourceModel; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; class News extends AbstractDb { protected $_serializableFields = [ 'store_id' => [null, [] ] ]; protected $_idFieldName = 'news_id'; protected function _construct() { $this->_init( 'news', 'news_id' ); } } |
- Magento 2.0.x trabaja con la función PHP serialize
- Magento 2.2.x trabaja con la función PHP json (json_encode, json_decode)
Ya estamos guardando los datos serializados en el campo store_id de nuestra tabla, pero ahora necesitamos recuperarlos para marcarlos como seleccionados si hay coincidencias.
Para ello necesitamos modificar nuestro DataProvider que se encarga de recuperar los datos de nuestra tabla para nuestro componente Ui de formulario.
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 |
<?php namespace <vendor>\<module>\Model\News; use <vendor>\<module>\Model\ResourceModel\News\NewsFactory; use Magento\Ui\DataProvider\AbstractDataProvider; class DataProvider extends AbstractDataProvider { public function __construct( $name, $primaryFieldName, $requestFieldName, NewsFactory $newsFactory, array $meta = [], array $data = [] ) { $this->collection = $newsFactory->create(); parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); } public function getData(){ if (isset($this->loadedData)) { return $this->loadedData; } $items = $this->collection->getItems(); $this->loadedData = array(); foreach ($items as $news) { $this->loadedData[$news->getId()]['news'] = $news->getData(); } // datos serializados<br /> if (!empty($items)) { $store_id = $this->loadedData[$news->getId()]['news']['store_id'];<br /> if (!empty($store_id)) {<br /> $this->loadedData[$news->getId()]['news']['store_id'] = @unserialize($store_id); } } return $this->loadedData; } } |
Como veis hay que hace unserialize() de nuestros datos para que el componente UI puede leerlos correctamente.
Nuestro selector quedaría así:
En el caso que necesitemos mostrar este campo en nuestro componente UI listing, tendremos que incluir una nueva columna que lo indentifique.
1 2 3 4 5 6 7 8 9 |
<column name="store_id" class="<vendor>\<module>\Ui\Component\Listing\Column\StoreNames"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item> <item name="sortable" xsi:type="boolean">true</item> <item name="label" xsi:type="string" translate="true">Store</item> </item> </argument> </column> |
Y Crearemos la clase que se encarga de mostrar el nombre de las tiendas en las que se mostrará dicho registro:
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 |
namespace <vendor>\<module>\Ui\Component\Listing\Column; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\UrlInterface; use Magento\Cms\Block\Adminhtml\Page\Grid\Renderer\Action\UrlBuilder; use Magento\Store\Model\StoreManagerInterface; class StoreNames extends Column { protected $urlBuilder; protected $actionUrlBuilder; protected $_storeManager; public function __construct( ContextInterface $context, UiComponentFactory $uiComponentFactory, UrlInterface $urlBuilder, UrlBuilder $actionUrlBuilder, StoreManagerInterface $storeManager, array $components = [], array $data = [] ) { $this->urlBuilder = $urlBuilder; $this->actionUrlBuilder = $actionUrlBuilder; $this->_storeManager = $storeManager; parent::__construct($context, $uiComponentFactory, $components, $data); } public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { // get store id from our table $item['store_id'] = @unserialize($item['store_id']); // get stores from shop $stores = $this->_storeManager->getStores(true, false); foreach($stores as $store){ foreach ($item['store_id'] as $value) { if($store->getId() === $value){ $storeView = $store->getName(); if ($store->getName() == 'Admin') { $storeView = 'All'; } $storeName[] = $storeView; } } } $item[$this->getData('name')] = $storeName; $storeName = ''; } } return $dataSource; } } |
El resultado seria este: