2

I am looking into the way the new custom options works in Magento 2.1, looking through it, their doesn't seem to be an obvious way to inject your own uiComponents into this, since it is all written in an object, inside protected methods (so no plugins).

This is the class that seems to controll it.

\Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions

I though this would be an obvious thing you would want to modify, and previously this was easily possible by adding a renderer, which you still can and all the product custom options still do in the product_options.xml by adding a renderer

Am I missing something?

2
  • My answer hasn't helped you? Sep 9, 2016 at 12:50
  • Did you figure it out? did you try Siarhey Uchukhlebau's solution?
    – Zinat
    Oct 20, 2016 at 13:35

2 Answers 2

2

You can update UI elements (or custom options renderer) using plugin for the Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions::modifyMeta() :

/**
 * {@inheritdoc}
 */
public function modifyMeta(array $meta)
{
    $this->meta = $meta;

    $this->createCustomOptionsPanel();

    return $this->meta;
}

All UI components are stored in the $this->meta param. Example:

app/code/Vendor/Module/etc/adminhtml/di.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions">
        <plugin name="Vendor_Module::Options" type="Vendor\Module\Plugin\Product\Form\Modifier\CustomOptions\ModifyMeta" sortOrder="20" disabled="false"/>
    </type>
</config>

app/Vendor/Module/Plugin/Product/Form/Modifier/CustomOptions/ModifyMeta.php:

<?php

namespace Vendor\Module\Plugin\Product\Form\Modifier\CustomOptions;

use Magento\Catalog\Model\Locator\LocatorInterface;

class ModifyMeta
{

    /**
     * @var LocatorInterface
     */
    protected $locator;

    /**
     * @param LocatorInterface $locator
     */
    public function __construct
    (
        LocatorInterface $locator
    ) {
        $this->locator = $locator;
    }

    /**
     *  Add something to the product custom options component
     *
     * @param \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Options $subject
     * @param string $result
     * @return string
     */
    public function afterModifyMeta($subject, $result)
    {
        $gcoName = \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions::GROUP_CUSTOM_OPTIONS_NAME; // custom_options container

        if (!empty($result[$gcoName])) {
            $product = $this->locator->getProduct(); // current product
            $productId  = $product->getId();

            $result[$gcoName]['children'] = array_replace_recursive(
                $result[$gcoName]['children'],
                [
                    'new_element_name' => [ // element name
                        'arguments' => [
                            'data' => [
                                'config' => [
                                    // config data here @see \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions for examples
                                ],
                            ],
                        ],
                        'children' => []
                    ]
                ]
            );
        }

        return $result;
    }
}

To get the final elements (custom option values elements) use something like this:

$result[$gcoName]['children']['options']['children']['record']['children']['container_option']['children']['values']['children']['record']['children']

The array has to be similar to this:

array

This way you can add or modify UI elements on the product page (without rewrite).

-2

Ok, to be honest, I have no idea how I've done it (rather, what I've done differently from the last 24 hours) but ... I've done it.

Seriously. I have no idea at all why it wasn't working before and it is now, but I am totally new to M2 (and Magento) although not to programming.

So, this is what I have. No idea if it will be any help to you but I hope so.

in my module (MyCompany_CustomProducts) at app/code/MyCompany/CustomProducts/, I have this di.xml under etc/ which has

<?xml version="1.0"?>    
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions" type="MyCompany\CustomProducts\Ui\DataProvider\Product\Form\Modifier\CustomOptions" />
</config>

Then in app/code/MyCompany/CustomProducts/Ui/DataProvider/Product/Form/Modifier/CustomOptions.php I have

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace MyCompany\CustomProducts\Ui\DataProvider\Product\Form\Modifier;


use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Catalog\Model\ProductOptions\ConfigInterface;
use Magento\Catalog\Model\Config\Source\Product\Options\Price as ProductOptionsPrice;
use Magento\Framework\UrlInterface;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Ui\Component\Modal;
use Magento\Ui\Component\Container;
use Magento\Ui\Component\DynamicRows;
use Magento\Ui\Component\Form\Fieldset;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Element\Checkbox;
use Magento\Ui\Component\Form\Element\ActionDelete;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Ui\Component\Form\Element\DataType\Number;
use Magento\Framework\Locale\CurrencyInterface;


class CustomOptions extends \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions
{

    protected function getSelectTypeGridConfig($sortOrder)
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'addButtonLabel' => __('Add Value'),
                        'componentType' => DynamicRows::NAME,
                        'component' => 'Magento_Ui/js/dynamic-rows/dynamic-rows',
                        'additionalClasses' => 'admin__field-wide',
                        'deleteProperty' => static::FIELD_IS_DELETE,
                        'deleteValue' => '1',
                        'renderDefaultRecord' => false,
                        'sortOrder' => $sortOrder,
                    ],
                ],
            ],
            'children' => [
                'record' => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'componentType' => Container::NAME,
                                'component' => 'Magento_Ui/js/dynamic-rows/record',
                                'positionProvider' => static::FIELD_SORT_ORDER_NAME,
                                'isTemplate' => true,
                                'is_collection' => true,
                            ],
                        ],
                    ],
                    'children' => [
                        static::FIELD_TITLE_NAME => $this->getTitleFieldConfig(10),
                        static::FIELD_PRICE_NAME => $this->getPriceFieldConfig(20),
                        static::FIELD_PRICE_TYPE_NAME => $this->getPriceTypeFieldConfig(30, ['fit' => true]),
                       // static::FIELD_SKU_NAME => $this->getSkuFieldConfig(40),
                        static::FIELD_SORT_ORDER_NAME => $this->getPositionFieldConfig(50),
                        static::FIELD_IS_DELETE => $this->getIsDeleteFieldConfig(60)
                    ]
                ]
            ]
        ];
    }



}

This extends the base class and makes one change to the output of the dropdown/select option (removes the SKU - not what I want to do, I actually want to add a quantity field but this was an easy way to test). It does that by commenting out this line

// static::FIELD_SKU_NAME => $this->getSkuFieldConfig(40),

I cleared the cache and ran bin/magento setup:upgrade and - finally, for God knows WHAT reason - it works. When I load a product in the backend with a custom option of dropdown type, it now doesn't show the SKU.

NOW, I have to make it do what I want, but at least I have this bit done...

1
  • Not sure why this was downvoted, it works for me. It'd be nice if the person who did it actually said why - is something wrong? Anyway, I found the main issue that was causing problems - it was simply file ownership. If a file is owned by the wrong user and then setup is run, it can cause problems. Deleting var/cache, reset ownership and setup again, and that problems goes away.
    – John122
    Jun 30, 2016 at 6:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.