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
1. 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>
2. Create Column file (path as per class name)
<?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;
}
}
3. 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 :-)