I am using a standard Material-Table. I would like to render the column status like in the image down below. I could use ANT Design to do this, but Material-Table requires a lot less code to allow for searching and filtering.
Here is a very simple example of my table. I am using some options to set the header color, font etc. I am also using rowStyle to alternate colors on each row.
const [intakes, setIntakes] = useState([]);
const columns = [
{ title: "Status", field: "Status" },
];
function Table() {
return (
<MaterialTable data={intakes.intakes} columns={columns} />
);
}
In your columns definition, you will need to use the render property of the column object. A similar question is here
code example:
<MaterialTable
columns={[
{ title: "Name", field: "name" },
{ title: "Surname", field: "surname" },
{ title: "Id", field: "tableData.id" },
{ title: "Id+1", render: rowData => rowData.tableData.id + 1 },
]}/>
This is the important part here:
render: rowData => rowData.tableData.id + 1
using the rowData, you can call a function here using a specific field other than the id in the example (let's say
render: rowData => generateFlagText(rowData.tableData.Status)
And your function should return some div with classNames to display those status
Related
I have a slickgrid cell with an autocompletion and a custom formatter. The cell value is a key field of dynamically loading autocompletion list. The list is shown as labels (e.g. Contract: ABCDEF-123, thick:10, width:210, City: Chicago) and when I select one it appears in the according input field. The point is that the formatter does not know that label, it only knows the key (order_id).
function contractFormatter(row, cell, value, columnDef, dataContext) {
var res = '';
var val = get_contract_list()[value] ? get_contract_list()[value]['label'] : '';
res = '<span class="' + getSpanClass() + '" style="float: left;"></span>\n\
'+ (val =='' ? '<span style="color:slategrey;"> Enter 3 symbols </span>' + val : val) + '';
return res;
}
The function get_contract_list returns the whole list of contracts and it is very big, so it was decided to make that list dynamic. So the function is empty now and it would be nice just to take the selected label into val.
Is there any way to achieve it?
You have to remember that Formatters are synchronous and it must return right away in a string format, if it requires a lot of processing power while staying synchronous then you'll end up slowing down your grid. You should probably cache your list once in a separate variable and use it afterward instead of reloading the list every time. If you load something that takes time and is asynchronous (a delayed output) then you'll want to look up the asyncPostRenderer (you can see this Example)
So going back to displaying the associated key to a label, I've done something similar in my lib in this Example and a live demo here, in my use case the value is a key index and I use the complexityLevelList to find its associated object which I can then read its label to display in the formatter.
export class MyExample {
complexityLevelList = [
{ value: 0, label: 'Very Simple' },
{ value: 1, label: 'Simple' },
{ value: 2, label: 'Straightforward' },
{ value: 3, label: 'Complex' },
{ value: 4, label: 'Very Complex' },
];
prepareGrid() {
this.columnDefinitions = [
{
id: 'complexity', name: 'Complexity', field: 'complexity', minWidth: 100,
formatter: (_row, _cell, value) => this.complexityLevelList[value].label,
filter: {
model: Filters.multipleSelect,
collection: this.complexityLevelList
},
editor: {
model: Editors.singleSelect,
collection: this.complexityLevelList,
massUpdate: true
},
},
];
}
}
Note that the Filters & Editors are specific to my lib Slickgrid-Universal, but you should get the idea on how to refactor your code to make it work.
I am using ag-Grid table in a Reactjs app, a snippet of my code can be seen below:
const columnsDef = [
.
.
{
headerName: 'Side',
field: UI_FIELDS.SIDE,
width: 70,
cellRenderer: sideRenderer,
cellRendererParams: {
value: "BUY"
}
},
.
.
]
function sideRenderer(params) {
const value = _.get(params, 'value') || '';
const styleSuffix = _.isEmpty(value) ? 'default' : value.toLowerCase();
return `<span class="side-renderer side-renderer-${styleSuffix}">${value}</span>`;
}
I have hardcoded value: "BUY" in my cellRendererParams for the moment, but I want this to actually be equal to whatever is in that cell for that column, which could be either BUY or SELL.
This value affects what css is applied to the text, a BUY value will be coloured Green and a Sell value will be colour Red.
How do I set value to be equal to the actual text in the cell and not be hard coded like this?
You can do something like this
const columnsDef = [
{
headerName: 'Side',
field: UI_FIELDS.SIDE,
width: 70,
cellRenderer: (params) => params.value.toLowerCase() === 'buy' ? `<span class="side-renderer side-renderer-buy">${params.value}</span>` : `<span class="side-renderer side-renderer-sell">${params.value}</span>
}
]
I guess this is what you want? If not please explain in more details what you need.
Edit: You do not really need to pass the cell renders params, you can get the cell's value using params.value
Thanks 'A Ghanima' for mentioning to use params.value, this helped me come up with the following solution which works
{
headerName: 'Side',
field: UI_FIELDS.SIDE,
width: 70,
cellRenderer: sideRenderer,
cellRendererParams: (params) => { value: params.value }
}
I'm trying to display some items in a list in a specific order but I would like some orientation since I'm kind of new working with sap ui 5
Heres the code I have:
var oSelectMedioPago = new sap.m.Select({
enabled: {
path: 'Enabled'
},
selectedKey: {
path: 'path'
},
items: {
path: "Items",
template: new sap.ui.core.ListItem({
key: '{key}',
text: '{text}'
}),
templateShareable: false
},
change: function(oEvent) {
//do something
});
How can I change the order of these items to be displayed by (for example) their property 'text' or something more general just like ascending or descending order?
Yes, you can do that! In binding items of the Select control just add a sorter as follows:
items: {
path: "Items",
> sorter : {
> path : 'text'
> },
template: new sap.ui.core.ListItem({
key: '{key}',
text: '{text}'
}),
Here's a working example of a sorter using Northwind oData: http://veui5infra.dhcp.wdf.sap.corp:8080/snippix/#63753
Learn about Sorting in SAPUI5 :Sorting and Grouping
Read more information on sap.ui.model.Sorter
Let me know if this helps:-)
For some reason I need to define a hidden column when using KendoUI grid:
var fields = {
ID: { type: "string", editable: true, nullable: false },
HideID : { type: "string", editable: false, nullable: false ,hidden: true },
Name: { type: "string", editable: true, nullable: false }
};
var ColumnsDefine = [
{ field: "ID", title: "ID", width: 100 },
{ field: "HideID", hidden: true },
{ field: "Name", title: "Name", width: 100 }
];
I change the HideID column value using JavaScript (operate the dataItem) without editing the grid's record.
And the JavaScript code to change the hidden field is like below (it's inside a command-click function)
var tr = $(e.target).closest("tr");
var data = this.dataItem(tr);
data.HideID = "123";
Now the problem is when I click the default update button, the background update method is not being called because I didn't make changes to any visible column. But if I modify any visible columns and click update, both the HideID and another field will be updated successfully in the background.
What should I do to notify the KendoUI grid that its data has been changed and fire the update method by clicking the update button?
Your grid dataItem will be a kendo.data.ObservableObject; you need to set your HideID property in such a way that the kendo framework sees the change, using it's set() method:
var tr = $(e.target).closest("tr");
var data = this.dataItem(tr);
data.set("HideID","123");
Once you've done that, you should find that it's dirty field is set to true. That signals to the datasource that this object has changes which need to be saved via the update method.
See also this article which gives a good explanation of how the observableObject can be used for binding https://docs.telerik.com/kendo-ui/framework/mvvm/observableobject#set-field-values
Hope this helps!
I am in the process of learning Backbone.js and using BackGrid to render data and provide the end user a way to edit records on an Microsoft MVC website. For the purposes of this test grid I am using a Vendor model. The BackGrid makes the data editable by default (which is good for my purpose). I have added the following JavaScript to my view.
var Vendor = Backbone.Model.extend({
initialize: function () {
Backbone.Model.prototype.initialize.apply(this, arguments);
this.on("change", function (model, options) {
if (options && options.save === false) return;
model.url = "/Vendor/BackGridSave";
model.save();
});
}
});
var PageableVendors = Backbone.PageableCollection.extend(
{
model: Vendor,
url: "/Vendor/IndexJson",
state: {
pageSize: 3
},
mode: "client" // page entirely on the client side.
});
var pageableVendors = new PageableVendors();
//{ data: "ID" },
//{ data: "ClientID" },
//{ data: "CarrierID" },
//{ data: "Number" },
//{ data: "Name" },
//{ data: "IsActive" }
var columns = [
{
name: "ID", // The key of the model attribute
label: "ID", // The name to display in the header
editable: false, // By default every cell in a column is editable, but *ID* shouldn't be
// Defines a cell type, and ID is displayed as an integer without the ',' separating 1000s.
cell: Backgrid.IntegerCell.extend({
orderSeparator: ''
})
}, {
name: "ClientID",
label: "ClientID",
cell: "integer" // An integer cell is a number cell that displays humanized integers
}, {
name: "CarrierID",
label: "CarrierID",
cell: "number" // A cell type for floating point value, defaults to have a precision 2 decimal numbers
}, {
name: "Number",
label: "Number",
cell: "string"
}, {
name: "Name",
label: "Name",
cell: "string"
},
{
name: "IsActive",
label: "IsActive",
cell: "boolean"
}
];
// initialize a new grid instance.
var pageableGrid = new Backgrid.Grid({
columns: [
{
name:"",
cell: "select-row",
headercell: "select-all"
}].concat(columns),
collection: pageableVendors
});
// render the grid.
var $p = $("#vendor-grid").append(pageableGrid.render().el);
// Initialize the paginator
var paginator = new Backgrid.Extension.Paginator({
collection: pageableVendors
});
// Render the paginator
$p.after(paginator.render().el);
// Initialize a client-side filter to filter on the client
// mode pageable collection's cache.
var filter = new Backgrid.Extension.ClientSideFilter({
collection: pageableVendors,
fields: ['Name']
});
// REnder the filter.
$p.before(filter.render().el);
//Add some space to the filter and move it to teh right.
$(filter.el).css({ float: "right", margin: "20px" });
// Fetch some data
pageableVendors.fetch({ reset: true });
#{
ViewBag.Title = "BackGridIndex";
}
<h2>BackGridIndex</h2>
<div id="vendor-grid"></div>
#section styles {
#Styles.Render("~/Scripts/backgrid.css")
#Styles.Render("~/Scripts/backgrid-select-all.min.css")
#Styles.Render("~/Scripts/backgrid-filter.min.css")
#Styles.Render("~/Scripts/backgrid-paginator.min.css")
}
#section scripts {
#Scripts.Render("~/Scripts/underscore.min.js")
#Scripts.Render("~/Scripts/backbone.min.js")
#Scripts.Render("~/Scripts/backgrid.js")
#Scripts.Render("~/Scripts/backgrid-select-all.min.js")
#Scripts.Render("~/Scripts/backbone.paginator.min.js")
#Scripts.Render("~/Scripts/backgrid-paginator.min.js")
#Scripts.Render("~/Scripts/backgrid-filter.min.js")
#Scripts.Render("~/Scripts/Robbys/BackGridIndex.js")
}
When the user edits a row, it successfully fires the hits the model.Save() method and passes the model to the save Action, in this case BackGridSave and it successfully saves the record that changed, but seems to save all of the vendors in model when only one of the vendors changed. Is there a way from the JavaScript/Backbone.js/BackGrid to only pass one Vendor - the vendor that changed?
Update: I realized that it is not sending every vendor, but it is sending the same vendor multiple times as though the change event was firing multiple times.
I guess I answered my own question. Well, at least I am getting the desired result. I just added a call to off after the first on. Seems like this would not be necessary though.
var Vendor = Backbone.Model.extend({
initialize: function () {
Backbone.Model.prototype.initialize.apply(this, arguments);
this.on("change", function (model, options) {
if (options && options.save === false) return;
model.url = "/Robbys/BackGridSave";
model.save();
model.off("change", null, this); // prevent the change event from being triggered many times.
});
}
});