Magento 2 - add Multiselect Store Views in admin Form
-
03-10-2020 - |
题
I am developing a custom module in Magento 2. I would like to add to the editing form a multiselect to allow users to select the store view. In Magento 1.9 it is done in this way:
$fieldset->addField('store_id', 'multiselect', array(
'name' => 'stores[]',
'label' => Mage::helper('myhelper')->__('Store View'),
'title' => Mage::helper('myhelper')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true),
));
How can this be done in Magento 2?
解决方案
You should inject class Magento\Store\Model\System\Store
in the constructor and declare a global variable.
E.g:
public function __construct(
//...,
Magento\Store\Model\System\Store $systemStore
) {
//...
$this->_systemStore = $systemStore;
}
protected function _prepareForm()
{
//...
$fieldset->addField(
'store_ids',
'multiselect',
[
'name' => 'store_ids[]',
'label' => __('Store Views'),
'title' => __('Store Views'),
'required' => true,
'values' => $this->_systemStore->getStoreValuesForForm(false, true),
]
);
}
I hope it was helpful.
其他提示
For save why not to just implode the array
$data['store_ids'] = implode(',', $this->getRequest()->getParam('store_ids'));
In addition to adding the field to your form (see Bill's accepted answer), you need logic to save this field to the database. Because it is a compound field (a model might apply to more than one store view) it is good practice to save this to a separate table (normalization principle).
Use a UpgradeSchema to create a table with the _store
suffix. This has two columns: item_id
and store_id
. You might configure indices and/or foreign keys for performance gains but it's not strictly required. I assume you know how to do that so I won't post any code there.
Then in your model you need to add the additional logic for loading and saving to that second table. In my example I have model MyItem
with table my_items
so I need to create a table my_items_store
and add the following functions to my class in Vendor\NameSpace\Model\Resource\MyItem
:
/**
* @param \Magento\Framework\Model\AbstractModel $object
* @return void
*/
protected function saveStore($object)
{
$condition = $this->getConnection()->quoteInto('item_id = ?', $object->getId());
$this->getConnection()->delete($this->getTable('my_items_store'), $condition);
foreach ((array)$object->getData('store_ids') as $store) {
$storeArray = [
'item_id' => $object->getId(),
'store_id' => $store,
];
$this->getConnection()->insert(
$this->getTable('my_items_store'),
$storeArray
);
}
}
/**
* @param \Magento\Framework\Model\AbstractModel $object
* @return $this
*/
protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
{
if (!$object->getIsMassStatus()) {
$this->saveStore($object);
}
return parent::_afterSave($object);
}
/**
* @param \Magento\Framework\Model\AbstractModel $object
* @return \Magento\Framework\Model\AbstractModel
*/
public function loadStore(\Magento\Framework\Model\AbstractModel $object)
{
$select = $this->getConnection()->select()
->from($this->getTable('my_items_store'))
->where('item_id = ?', $object->getId());
if ($data = $this->getConnection()->fetchAll($select)) {
$array = [];
foreach ($data as $row) {
$array[] = $row['store_id'];
}
$object->setData('store_id', $array);
}
return $object;
}
/**
* @param \Magento\Framework\Model\AbstractModel $object
* @return $this
*/
protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
{
if (!$object->getIsMassDelete()) {
$this->loadStore($object);
}
return parent::_afterLoad($object);
}
The function _afterSave()
is called automatically when the save()
function is called on the Model. The same goes for _afterLoad()
when loading the Model. Copy these functions to your model, change the table to the name of your newly created table and you're good to go!