2

In my custom module grid i have to use custom grid column which render a field and create custom html content

how to implement it in Magento 2

2

in ui listing xml add below code in side columns tag

<column name="manufacturers" class="NAMEPACE\MODULENAME\Ui\Component\Listing\Column\Product\Manufacturers">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="component" xsi:type="string">NAMEPACE_MODULENAME/js/columns/html</item>
                    <item name="sortable" xsi:type="boolean">false</item>
                    <item name="altField" xsi:type="string">name</item>
                    <item name="label" xsi:type="string" translate="true">Manufacturers</item>
                    <item name="sortOrder" xsi:type="number">90</item>
                </item>
            </argument>
        </column>

Create Column file

<?php
/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace NAMEPACE\MODULENAME\Ui\Component\Listing\Column\Product;

use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Framework\View\Element\UiComponent\ContextInterface;

class Manufacturers extends \Magento\Ui\Component\Listing\Columns\Column
{
    /**
     * Column name
     */
    const NAME = 'column.manufacturers';
    /**
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param \Magento\Framework\Locale\CurrencyInterface $localeCurrency
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param array $components
     * @param array $data
     */
    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        array $components = [],
        array $data = []
    ) {
        parent::__construct($context, $uiComponentFactory, $components, $data);
    }

    /**
     * Prepare Data Source
     *
     * @param array $dataSource
     * @return array
     */
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {

            $fieldName = $this->getData('name');
            foreach ($dataSource['data']['items'] as & $item) {
                if (isset($item[$fieldName])) {
                    $html = '';
                    $manufacturers = unserialize($item[$fieldName]);
                    if (!empty($manufacturers)) {
                        foreach ($manufacturers as $manufacturer) {
                            if ($manufacturer['primary'] == 'Y') {
                                $html .= '<strong>';
                            }

                            $html .= $manufacturer['name'];

                            if (!empty($manufacturer['product_code'])) {
                                $html .= ' | ' . __('SKU') . ': ' . $manufacturer['product_code'];
                            }

                            if ($manufacturer['primary'] == 'Y') {
                                $html .= '</strong>';
                            }

                            $html .= '<br />';
                        }
                    }
                    $item[$fieldName] = $html;
                }
            }
        }

        return $dataSource;
    }
}

create custom js file to reneder html conent

path :- NAMESPACE/MODULENAME/view/adminhtml/web/js/columns/html.js

/**
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define([
    'underscore',
    'uiRegistry',
    'mageUtils',
    'uiElement'
], function (_, registry, utils, Element) {
    'use strict';

    return Element.extend({
        defaults: {
            headerTmpl: 'ui/grid/columns/text',
            bodyTmpl: 'ui/grid/cells/html',
            disableAction: false,
            controlVisibility: true,
            sortable: true,
            sorting: false,
            visible: true,
            draggable: true,
            fieldClass: {},
            ignoreTmpls: {
                fieldAction: true
            },
            statefull: {
                visible: true,
                sorting: true
            },
            imports: {
                exportSorting: 'sorting'
            },
            listens: {
                '${ $.provider }:params.sorting.field': 'onSortChange'
            },
            modules: {
                source: '${ $.provider }'
            }
        },

        /**
         * Initializes column component.
         *
         * @returns {Column} Chainable.
         */
        initialize: function () {
            this._super()
                .initFieldClass();

            return this;
        },

        /**
         * Initializes observable properties.
         *
         * @returns {Column} Chainable.
         */
        initObservable: function () {
            this._super()
                .track([
                    'visible',
                    'sorting',
                    'disableAction'
                ])
                .observe([
                    'dragging'
                ]);

            return this;
        },

        /**
         * Extends list of field classes.
         *
         * @returns {Column} Chainable.
         */
        initFieldClass: function () {
            _.extend(this.fieldClass, {
                _dragging: this.dragging
            });

            return this;
        },

        /**
         * Applies specified stored state of a column or one of its' properties.
         *
         * @param {String} state - Defines what state should be used: saved or default.
         * @param {String} [property] - Defines what columns' property should be applied.
         *      If not specified, then all columns stored properties will be used.
         * @returns {Column} Chainable.
         */
        applyState: function (state, property) {
            var namespace = this.storageConfig.root;

            if (property) {
                namespace += '.' + property;
            }

            this.storage('applyStateOf', state, namespace);

            return this;
        },

        /**
         * Sets columns' sorting. If column is currently sorted,
         * than its' direction will be toggled.
         *
         * @param {*} [enable=true] - If false, than sorting will
         *      be removed from a column.
         * @returns {Column} Chainable.
         */
        sort: function (enable) {
            if (!this.sortable) {
                return this;
            }

            enable !== false ?
                this.toggleSorting() :
                this.sorting = false;

            return this;
        },

        /**
         * Sets descending columns' sorting.
         *
         * @returns {Column} Chainable.
         */
        sortDescending: function () {
            if (this.sortable) {
                this.sorting = 'desc';
            }

            return this;
        },

        /**
         * Sets ascending columns' sorting.
         *
         * @returns {Column} Chainable.
         */
        sortAscending: function () {
            if (this.sortable) {
                this.sorting = 'asc';
            }

            return this;
        },

        /**
         * Toggles sorting direction.
         *
         * @returns {Column} Chainable.
         */
        toggleSorting: function () {
            this.sorting === 'asc' ?
                this.sortDescending() :
                this.sortAscending();

            return this;
        },

        /**
         * Checks if column is sorted.
         *
         * @returns {Boolean}
         */
        isSorted: function () {
            return !!this.sorting;
        },

        /**
         * Exports sorting data to the dataProvider if
         * sorting of a column is enabled.
         */
        exportSorting: function () {
            if (!this.sorting) {
                return;
            }

            this.source('set', 'params.sorting', {
                field: this.index,
                direction: this.sorting
            });
        },

        /**
         * Checks if column has an assigned action that will
         * be performed when clicking on one of its' fields.
         *
         * @returns {Boolean}
         */
        hasFieldAction: function () {
            return !!this.fieldAction || !!this.fieldActions;
        },

        /**
         * Applies action described in a 'fieldAction' property
         * or actions described in 'fieldActions' property.
         *
         * @param {Number} rowIndex - Index of a row which initiates action.
         * @returns {Column} Chainable.
         *
         * @example Example of fieldAction definition, which is equivalent to
         *      referencing to external component named 'listing.multiselect'
         *      and calling its' method 'toggleSelect' with params [rowIndex, true] =>
         *
         *      {
         *          provider: 'listing.multiselect',
         *          target: 'toggleSelect',
         *          params: ['${ $.$data.rowIndex }', true]
         *      }
         */
        applyFieldAction: function (rowIndex) {
            if (!this.hasFieldAction() || this.disableAction) {
                return this;
            }

            if (this.fieldActions) {
                this.fieldActions.forEach(this.applySingleAction.bind(this, rowIndex), this);
            } else {
                this.applySingleAction(rowIndex);
            }

            return this;
        },

        /**
         * Applies single action
         *
         * @param {Number} rowIndex - Index of a row which initiates action.
         * @param {Object} action - Action (fieldAction) to be applied
         *
         */
        applySingleAction: function (rowIndex, action) {
            var callback;

            action = action || this.fieldAction;
            action = utils.template(action, {
                column: this,
                rowIndex: rowIndex
            }, true);

            callback = this._getFieldCallback(action);

            if (_.isFunction(callback)) {
                callback();
            }
        },

        /**
         * Returns field action handler if it was specified.
         *
         * @param {Object} record - Record object with which action is associated.
         * @returns {Function|Undefined}
         */
        getFieldHandler: function (record) {
            if (this.hasFieldAction()) {
                return this.applyFieldAction.bind(this, record._rowIndex);
            }
        },

        /**
         * Creates action callback based on its' data.
         *
         * @param {Object} action - Actions' object.
         * @returns {Function|Boolean} Callback function or false
         *      value if it was impossible create a callback.
         */
        _getFieldCallback: function (action) {
            var args     = action.params || [],
                callback = action.target;

            if (action.provider && action.target) {
                args.unshift(action.target);

                callback = registry.async(action.provider);
            }

            if (!_.isFunction(callback)) {
                return false;
            }

            return function () {
                callback.apply(callback, args);
            };
        },

        /**
         * Ment to preprocess data associated with a current columns' field.
         *
         * @param {Object} record - Data to be preprocessed.
         * @returns {String}
         */
        getLabel: function (record) {
            return record[this.index];
        },

        /**
         * Returns list of classes that should be applied to a field.
         *
         * @returns {Object}
         */
        getFieldClass: function () {
            return this.fieldClass;
        },

        /**
         * Returns path to the columns' header template.
         *
         * @returns {String}
         */
        getHeader: function () {
            return this.headerTmpl;
        },

        /**
         * Returns path to the columns' body template.
         *
         * @returns {String}
         */
        getBody: function () {
            return this.bodyTmpl;
        },

        /**
         * Listener of the providers' sorting state changes.
         *
         * @param {Srting} field - Field by which current sorting is performed.
         */
        onSortChange: function (field) {
            if (field !== this.index) {
                this.sort(false);
            }
        }
    });
});

Clear cache :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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