I find a solution.
I hope this can help you.
Find the row in your ui component js file where is write the item tag with name "component":
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
</item>
</argument>
and change it like:
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">YourVendor_YourModule/js/grid/provider</item>
</item>
</argument>
The path of that js file is: vendor/magento/module-ui/view/base/web/js/grid/provider.js
So the new path of your new custom js file will be: app/code/YourVendor/YourModule/view/base/web/js/grid/provider.js
Change the method "processData" in the way that let you calculate the total of the price column, for example like this:
CHECK MODIFIED CODE COMMENT.JUST CHECK processData
function because just changed that function and other function copied from vendor\magento\module-ui\view\base\web\js\grid/provider.js
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'underscore',
'mageUtils',
'uiElement',
'Magento_Ui/js/modal/alert',
'mage/translate'
], function ($, _, utils, Element, alert, $t) {
'use strict';
return Element.extend({
defaults: {
listens: {
params: 'reload'
}
},
/**
* Initializes provider component.
*
* @returns {Provider} Chainable.
*/
initialize: function () {
utils.limit(this, 'reload', 300);
_.bindAll(this, 'onReload');
return this._super();
},
/**
* Initializes provider config.
*
* @returns {Provider} Chainable.
*/
initConfig: function () {
this._super();
this.setData({
items: [],
totalRecords: 0
});
return this;
},
/**
*
* @param {Object} data
* @returns {Provider} Chainable.
*/
setData: function (data) {
data = this.processData(data);
this.set('data', data);
return this;
},
/**
* Reloads data with current parameters.
*/
reload: function () {
this.trigger('reload');
if (this.request && this.request.readyState !== 4) {
this.request.abort();
}
this.request = $.ajax({
url: this['update_url'],
method: 'GET',
data: this.get('params'),
dataType: 'json'
});
this.request
.done(this.onReload)
.error(this.onError);
},
/* START MODIFIED CODE */
processData: function (data) {
var items = data.items;
var total = 0;
_.each(items, function (record, index) {
record._rowIndex = index;
total += parseFloat(record.price);//price is column of custom table
});
jQuery("#custom_total_value").text(total);
return data;
},
/* END MODIFIED CODE */
/**
* Handles reload error.
*/
onError: function (xhr) {
if (xhr.statusText === 'abort') {
return;
}
alert({
content: $t('Something went wrong.')
});
},
/**
* Handles successful data reload.
*
* @param {Object} data - Retrieved data object.
*/
onReload: function (data) {
this.setData(data)
.trigger('reloaded');
}
});
});
record is an object inside the collection which is printed in the grid.
After you can add a block in your layout file:
<referenceContainer name="content">
<uiComponent name="your_listing"/>
<block class="Magento\Framework\View\Element\Template" template="YourVendor_YourModuke::custom_total.phtml" />
</referenceContainer>
Inside custom_total.phtml I write:
<span><b>Total</b></span> <span id="custom_total_value"></span>
So I can see a row down the grid where is printed the total.
To see the changes in the grid remove all static file and cache with the command:
rm -rf var/cache/* var/page_cache/* var/view_preprocessed/* pub/static/*
inside your root magento directory.
Then recompile static content:
php bin/magento setup:static-content:deploy your_language
EDIT: Alternatively you can modify data object returned by processData method, adding another record with same attributes of a normal record but with totals as values. In this way probably you can have a new row inside the grid. I didn't try this solution but I think it will work.
In your app/code/Test/Testimonial/view/adminhtml/ui_component/testimonial_blog_listing.xml
add in the column tag the class attribute:
<column name="nameofyourcolumn" class="YourVendor\YourModule\Ui\Component\Listing\Column\MyColumn">
MyColumn class is:
<?php
namespace YourVendor\YourModule\Ui\Component\Listing\Column;
use Magento\Ui\Component\Listing\Columns\Column;
use Magento\Framework\DataObject;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
class MyColumn extends Column{
public function __construct(
ContextInterface $context,
UiComponentFactory $uiComponentFactory,
\Magento\Backend\Model\Auth\Session $authSession,
array $components = [],
array $data = []
) {
if(!in_array(1,$authSession->getUser()->getRoles())){
$data = [];
}
parent::__construct($context, $uiComponentFactory,$components, $data);
}
}
in your case YourVendor/YourModule is equal to Test/Testimonial
in the $authSession variable you have all information about the authenticated user.
In the if which you can read above, I want that if the authenticated user is not an administrator (1 is the ID of the administrators group for me) don't show the column. To achieve this I put an empty array in $data variable, which contains all data printed in the column, as result I don't see anymore the column.
Best Answer
If you need to create join in any grid then you need to existing grid collection. For this example, the grid has own collection. So you can add following code to grid collection.
File:
SR/Weblog/Model/ResourceModel/BlogPosts/Grid/Collection.php
Also, you can use: