Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a magento.stackexchange
scroll top