How to add product image on admin order creation page in Magento 2?

10 June 2024

next article
Oleg Litvinchuk

Backend Developer

Oleg  Litvinchuk
How to add product image on admin order creation page in Magento 2?

About the author: Oleg Litvinchuk, a backend developer with extensive experience working with eCommerce projects on various CMS, including Magento 2. In his opinion, it is always better to invest more in development and create perfect and effective tools than to ignore the difficulties that the company's staff will suffer from and business in general.


Images are an integral part of any website that sells goods or services. For material products, this is a must-have — because no one wants to buy a "cat in a bag" and wants to see what they should get from a deal with an online store. For intangible products, such as services, thematic images are also important, as they create an associative series for the customer, which strengthens the desire to purchase right here and now. But product images are no less important for company employees who directly place customer orders.

Ordering in Magento 2

Undoubtedly, Magento 2 is one of the best CMS in the world for the development of large eCommerce projects. It is a powerful and flexible system that can be completely customized to the needs of your business down to the smallest detail. However, among the basic functions, you will not be able to find absolutely everything that your business needs, because CMS authors cannot guess the thoughts of users from a distance. Therefore, this issue is solved by developers who supplement the functionality or customize its individual parts.

magento-2-order-grid.png

Magento 2 is best suited for the development of eCommerce projects where customer orders are the basis of the company's operations. Site administrators receive a notification about a new order in the dashboard and can view various details: buyer data, payment amount, product name and its characteristics, article number and much more. However, it is impossible to see what the user has purchased in the basic version of the CMS, since the display of attached product images is not provided. Therefore, if you need to display an image in the admin panel, you should refer to the code and create a small module — an addition to the system that extends its functions. And now I will show how it is done.

Module for displaying product images

Modules for Magento 2 can perform any functions, but for the correct operation of each of them, the prescribed rules should be followed. Let's go through the necessary steps to create a new module step by step.

Step 1

Create a file app\code\Avivi\ProductImageAdminOrder\registration.php and use the following code:

1
2
3
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="\Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid" type="Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\OverrideOrder\Create\Search\Grid"/>
</config>

Step 2

Create the following file app\code\Avivi\ProductImageAdminOrder\etc\module.xml and use the following code:

  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
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<?php

namespace Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\OverrideOrder\Create\Search;

use Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\DataProvider\ProductCollection;
use Magento\Framework\App\ObjectManager;

/**
 * Adminhtml sales order create search products block
 *
 */
class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
{
    /**
     * Sales config
     *
     * @var \Magento\Sales\Model\Config
     */
    protected $_salesConfig;

    /**
     * Session quote
     *
     * @var \Magento\Backend\Model\Session\Quote
     */
    protected $_sessionQuote;

    /**
     * Catalog config
     *
     * @var \Magento\Catalog\Model\Config
     */
    protected $_catalogConfig;

    /**
     * Product factory
     *
     * @var \Magento\Catalog\Model\ProductFactory
     */
    protected $_productFactory;

    /**
     * @var ProductCollection $productCollectionProvider
     */
    private $productCollectionProvider;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Backend\Helper\Data $backendHelper
     * @param \Magento\Catalog\Model\ProductFactory $productFactory
     * @param \Magento\Catalog\Model\Config $catalogConfig
     * @param \Magento\Backend\Model\Session\Quote $sessionQuote
     * @param \Magento\Sales\Model\Config $salesConfig
     * @param array $data
     * @param ProductCollection|null $productCollectionProvider
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Backend\Helper\Data $backendHelper,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Catalog\Model\Config $catalogConfig,
        \Magento\Backend\Model\Session\Quote $sessionQuote,
        \Magento\Sales\Model\Config $salesConfig,
        array $data = [],
        ProductCollection $productCollectionProvider = null
    ) {
        $this->_productFactory = $productFactory;
        $this->_catalogConfig = $catalogConfig;
        $this->_sessionQuote = $sessionQuote;
        $this->_salesConfig = $salesConfig;
        $this->productCollectionProvider = $productCollectionProvider
            ?: ObjectManager::getInstance()->get(ProductCollection::class);
        parent::__construct($context, $backendHelper, $data);
    }

    /**
     * Constructor
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('sales_order_create_search_grid');
        $this->setRowClickCallback('order.productGridRowClick.bind(order)');
        $this->setCheckboxCheckCallback('order.productGridCheckboxCheck.bind(order)');
        $this->setRowInitCallback('order.productGridRowInit.bind(order)');
        $this->setDefaultSort('entity_id');
        $this->setFilterKeyPressCallback('order.productGridFilterKeyPress');
        $this->setUseAjax(true);
        if ($this->getRequest()->getParam('collapse')) {
            $this->setIsCollapsed(true);
        }
    }

    /**
     * Retrieve quote store object
     *
     * @return \Magento\Store\Model\Store
     */
    public function getStore()
    {
        return $this->_sessionQuote->getStore();
    }

    /**
     * Retrieve quote object
     *
     * @return \Magento\Quote\Model\Quote
     */
    public function getQuote()
    {
        return $this->_sessionQuote->getQuote();
    }

    /**
     * Add column filter to collection
     *
     * @param \Magento\Backend\Block\Widget\Grid\Column $column
     * @return $this
     */
    protected function _addColumnFilterToCollection($column)
    {
        // Set custom filter for in product flag
        if ($column->getId() == 'in_products') {
            $productIds = $this->_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', ['in' => $productIds]);
            } else {
                if ($productIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', ['nin' => $productIds]);
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }

    /**
     * Prepare collection to be displayed in the grid
     *
     * @return $this
     */
    protected function _prepareCollection()
    {

        $attributes = $this->_catalogConfig->getProductAttributes();
        $store = $this->getStore();

        /* @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
        $collection = $this->productCollectionProvider->getCollectionForStore($store);
        $collection->addAttributeToSelect(
            $attributes
        );
        $collection->addAttributeToFilter(
            'type_id',
            $this->_salesConfig->getAvailableProductTypes()
        );

        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    /**
     * Prepare columns
     *
     * @return $this
     */
    protected function _prepareColumns()
    {
        $this->addColumn(
            'thumbnail',
            [
                'filter' => false,
                'sortable' => false,
                'header' => __('Images'),
                'name' => 'thumbnail',
                'inline_css' => 'thumbnail',
                'index' => 'image',
                'class' => 'image',
                'renderer' => 'Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\Product\Grid\Renderer\Image',
            ]
        );
        $this->addColumn(
            'entity_id',
            [
                'header' => __('ID'),
                'sortable' => true,
                'header_css_class' => 'col-id',
                'column_css_class' => 'col-id',
                'index' => 'entity_id'
            ]
        );
        $this->addColumn(
            'name',
            [
                'header' => __('Product'),
                'renderer' => \Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\Renderer\Product::class,
                'index' => 'name'
            ]
        );
        $this->addColumn('sku', ['header' => __('SKU'), 'index' => 'sku']);
        $this->addColumn(
            'price',
            [
                'header' => __('Price'),
                'column_css_class' => 'price',
                'type' => 'currency',
                'currency_code' => $this->getStore()->getCurrentCurrencyCode(),
                'rate' => $this->getStore()->getBaseCurrency()->getRate($this->getStore()->getCurrentCurrencyCode()),
                'index' => 'price',
                'renderer' => \Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\Renderer\Price::class
            ]
        );

        $this->addColumn(
            'in_products',
            [
                'header' => __('Select'),
                'type' => 'checkbox',
                'name' => 'in_products',
                'values' => $this->_getSelectedProducts(),
                'index' => 'entity_id',
                'sortable' => false,
                'header_css_class' => 'col-select',
                'column_css_class' => 'col-select'
            ]
        );

        $this->addColumn(
            'qty',
            [
                'filter' => false,
                'sortable' => false,
                'header' => __('Quantity'),
                'renderer' => \Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\Renderer\Qty::class,
                'name' => 'qty',
                'inline_css' => 'qty',
                'type' => 'input',
                'validate_class' => 'validate-number',
                'index' => 'qty'
            ]
        );

        return parent::_prepareColumns();
    }

    /**
     * Get grid url
     *
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl(
            'sales/*/loadBlock',
            ['block' => 'search_grid', '_current' => true, 'collapse' => null]
        );
    }

    /**
     * Get selected products
     *
     * @return mixed
     */
    protected function _getSelectedProducts()
    {
        $products = $this->getRequest()->getPost('products', []);

        return $products;
    }

    /**
     * Add custom options to product collection
     *
     * @return $this
     */
    protected function _afterLoadCollection()
    {
        $this->getCollection()->addOptionsToResult();
        return parent::_afterLoadCollection();
    }
}

Step 3

So we are almost close to our goal! Now create the following file app\code\Avivi\ProductImageAdminOrder\Block\Adminhtml\OverrideOrder\Create\Search\Grid.php using the following code:

 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
60
61
62
63
<?php
namespace Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\Product\Grid\Renderer;

use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\Asset\Repository;
use Magento\Catalog\Helper\ImageFactory;
use Magento\Framework\Image\AdapterFactory;
use Magento\Store\Model\StoreManager;
use Magento\Store\Model\ScopeInterface;

class Image extends AbstractRenderer
{
    private $_storeManager;
    private $helperImageFactory;
    private $assetRepos;
    private $adapterFactory;
    private $scopeConfig;
    private $storeManager;
    /**
     * @param \Magento\Backend\Block\Context $context
     * @param array $data
     */
    public function __construct(\Magento\Backend\Block\Context $context,
                                Repository $assetRepos,
                                ImageFactory $helperImageFactory,
                                AdapterFactory $adapterFactory,
                                StoreManager $storeManager,
                                StoreManagerInterface $storemanager, array $data = [])
    {
        $this->_storeManager = $storemanager;
        $this->assetRepos = $assetRepos;
        $this->helperImageFactory = $helperImageFactory;
        $this->adapterFactory = $adapterFactory;
        $this->storeManager = $storeManager;
        $this->scopeConfig = $context->getScopeConfig();

        parent::__construct($context, $data);
        $this->_authorization = $context->getAuthorization();
    }
    /**
     * Renders grid column
     *
     * @param Object $row
     * @return  string
     */
    public function render(DataObject $row)
    {
        $mediaDirectory = $this->_storeManager->getStore()->getBaseUrl(
            \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
        );

        if($this->_getValue($row)){
            $imageUrl = $mediaDirectory.'/catalog/product'.$this->_getValue($row);
        }else{
            $plUrl = $this->scopeConfig->getValue('catalog/placeholder/thumbnail_placeholder',ScopeInterface::SCOPE_STORE,0);
            $imageUrl = $mediaDirectory.'/catalog/product/placeholder/'.$plUrl;
        }
        return '<img src="'.$imageUrl.'" style="width: 5rem;border: 1px solid #d6d6d6;"/>';

    }
}

Step 4. The last one

Finally, create a file app\code\Avivi\ProductImageAdminOrder\Block\Adminhtml\Product\Grid\Renderer\Image.php and use the following code:

 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
60
61
62
63
<?php
namespace Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\Product\Grid\Renderer;

use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\Asset\Repository;
use Magento\Catalog\Helper\ImageFactory;
use Magento\Framework\Image\AdapterFactory;
use Magento\Store\Model\StoreManager;
use Magento\Store\Model\ScopeInterface;

class Image extends AbstractRenderer
{
    private $_storeManager;
    private $helperImageFactory;
    private $assetRepos;
    private $adapterFactory;
    private $scopeConfig;
    private $storeManager;
    /**
     * @param \Magento\Backend\Block\Context $context
     * @param array $data
     */
    public function __construct(\Magento\Backend\Block\Context $context,
                                Repository $assetRepos,
                                ImageFactory $helperImageFactory,
                                AdapterFactory $adapterFactory,
                                StoreManager $storeManager,
                                StoreManagerInterface $storemanager, array $data = [])
    {
        $this->_storeManager = $storemanager;
        $this->assetRepos = $assetRepos;
        $this->helperImageFactory = $helperImageFactory;
        $this->adapterFactory = $adapterFactory;
        $this->storeManager = $storeManager;
        $this->scopeConfig = $context->getScopeConfig();

        parent::__construct($context, $data);
        $this->_authorization = $context->getAuthorization();
    }
    /**
     * Renders grid column
     *
     * @param Object $row
     * @return  string
     */
    public function render(DataObject $row)
    {
        $mediaDirectory = $this->_storeManager->getStore()->getBaseUrl(
            \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
        );

        if($this->_getValue($row)){
            $imageUrl = $mediaDirectory.'/catalog/product'.$this->_getValue($row);
        }else{
            $plUrl = $this->scopeConfig->getValue('catalog/placeholder/thumbnail_placeholder',ScopeInterface::SCOPE_STORE,0);
            $imageUrl = $mediaDirectory.'/catalog/product/placeholder/'.$plUrl;
        }
        return '<img src="'.$imageUrl.'" style="width: 5rem;border: 1px solid #d6d6d6;"/>';

    }
}

Save all changes and check the result. Now the appearance of the list of orders in the admin panel of your Magento 2 has changed — a column with a thumbnail image of the product has been added:

image_2024-05-10_09-39-00.png555555

As you can see, solving the problem by creating a new module is not scary at all. However, it's always better to entrust development tasks to professionals: me and the Avivi team are always ready to help you develop Magento 2 projects.

Baner articles 2023 eng.png


Similar articles
Apply for a consultation

We will reach out to within 10 minutes