How to I change my react table accesssor value based on data conditionally? - javascript

const data = {
name:"test1",
fclPrice:100,
lclPrice:null,
total:"50"
}
and my two columns:
const Datatable = [
{ Header: 'Name', accessor: 'name' },
{ Header: 'Price', accessor:'?' },
{ Header: 'Total', accessor:'total' }
];
I want accessor to take the price key which has number
For eg : if fclprice:null and lclPrice:100 it should take lclPrice and viceversa

You can a set a value of an accessor to a function which will take as a first argument the object with your data. Then, you can pass whatever condition you want to it:
const Datatable = [
{ Header: 'Price', accessor: (data)=>data.fclPrice || data.lclPrice},
];

Related

VueGoodTable filter dropdown options vue2

I'm trying to populate possible dropdown options on vue good table. The idea is that I conduct an API call to the server to bring back what values can possibly go into the drop down and I'm trying to assign it to the column filter. However, I can't seem to get it to work.
<vue-good-table
:paginationOptions="paginationOptions"
:sort-options="sortOptions"
:isLoading.sync="isTableLoading"
:rows="rows"
:columns="columns"
:lineNumbers="true"
mode="remote"
:totalRows="totalRecords"
#on-row-click="onRowClick"
#on-page-change="onPageChange"
#on-sort-change="onSortChange"
#on-column-filter="onColumnFilter"
#on-per-page-change="onPerPageChange"
#on-search="onSearch"
:search-options="{
enabled: true
}"
styleClass="vgt-table striped bordered"
ref="table"
>
Fairly standard vgt set up.
columns: [
{
label: 'some column',
field: 'column1'
},
{
label: 'Customer',
field: 'customerName',
filterOptions: {
enabled: true,
placeholder: 'All',
filterDropdownItems: Object.values(this.customers)
}
},
{
label: 'other columns',
field: 'column234'
}
]
and the API call
methods: {
async load () {
await this.getTableOptions()
},
async getTableOptions () {
try {
var response = await axios.get(APICallUrl)
this.customers= []
for (var i = 0; i < response.data.customers.length; i++) {
this.customers.push({ value: response.data.customers[i].customerId, text: response.data.customers[i].customerName})
}
} catch (e) {
console.log('e', e)
}
}
The only thing that I thought of is that the table has finished rendering before the load method is complete. However just creating a static object in my data and assigning it to a filterDropDownItems yielded no better results. The result whenever I try to set it to an object is that the box is a type-in box rather than a dropdown.
You can make the table update after it's rendered by making columns a computed property. The other problem you have is this.customers is an Array but Object.values() expects an Object. You could use the Array.map function instead
this.customers.map(c => c.value)
Although according to the VueGoodTable docs an array of objects like you have should work just fine
computed: {
columns() {
return [
{
label: 'some column',
field: 'column1'
},
{
label: 'Customer',
field: 'customerName',
filterOptions: {
enabled: true,
placeholder: 'All',
filterDropdownItems: this.customers
}
},
{
label: 'other columns',
field: 'column234'
}
];
}
}

How to format date in ant table?

I have a table with 6 columns, one of these columns is a date, The default display format of the date is 2020-04-30T21:30:07.000Z I want to change it to 30-04-2020.
export const columns = [
{ title: `ID`, dataIndex: `invoice_id`},
{ title: `Invoice Number`, dataIndex: `invoice_number` },
{ title: `Amount`, dataIndex: `invoice_amount`},
{ title: `Store Name`, dataIndex: `store_name`},
{ title: `Supplier Name`, dataIndex: `supplier_name`},
{ title: `Creation Date`, dataIndex: `invoice_date`,},
]
<Table bordered columns={columns} dataSource={invoices_list} />
I believe there should be a way to pass date format to the columns. I looked into the ant table documentations but didn't find a solution.
Another way to implement it is to define a 'render' for a date column like
{
title: 'Published at',
dataIndex: 'publishedAt',
key: 'publishedAt',
width: 210,
render: ((date:string) => getFullDate(date)) }
and just utilize date formatting function getFullDate. In your case it can look like
export const getFullDate = (date: string): string => {
const dateAndTime = date.split('T');
return dateAndTime[0].split('-').reverse().join('-');
};
In this case you'll also avoid using external libraries and will have a function to format the date in other places.
After looking into the antd documentation (https://ant.design/components/table/#API) it doesn't seems to have a property to handle your case. You should duplicate your column invoices_date to invoices_date_printabble which will have the good format to be printed.
invoices_list.map(el => {
let date = new Date(el.invoices_date)
el.invoices_date_printabble = date.getDay()+"/"+date.getMonth()+"/"+date.getFullYear()
})
And now your list is printable.
export const columns = [
{ title: `ID`, dataIndex: `invoice_id`},
{ title: `Invoice Number`, dataIndex: `invoice_number` },
{ title: `Amount`, dataIndex: `invoice_amount`},
{ title: `Store Name`, dataIndex: `store_name`},
{ title: `Supplier Name`, dataIndex: `supplier_name`},
{ title: `Creation Date`, dataIndex: `invoices_date_printabble`},
]
<Table bordered columns={columns} dataSource={invoices_list} />
Another way to do it using moment.js library.
First install moment.js into your project
npm i moment
Second import it to your component
import moment from 'moment';
Third change date format:
let invoices=response.data
invoices.map(el => {
let date = moment(new Date(el.invoice_date));
el.invoice_date = date.format("DD/MM/YYYY")
})
this worked for me!
export const columns = [
{
title: "ID",
key: "key",
render: (record) => {
return (
<div>
<p>{moment(record.invoice_id).format("DD-MM-YYYY")}</p>
</div>
);
},
},
]
I think the easiest way would be to use moment.js in the render method of the column options:
Your moment format of your existing date can be found in the moment documentation.
For future reference you can always use a millisecond timestamp and convert to whatever date format you want with moment.
export const columns = [
....
{ title: "Creation Date",
dataIndex: "invoices_date",
render: (invoice_date) => { return (<p>{moment(invoices_date, **"Moment Format"**).format(DD-MM-YYYY)}</p>)},
]

How to add a style element inside a cell when the text inside changes to another value

I'm working on a ReactJS app which shows from an API a table populated of flights information. One of the columns is called status and it is changing value when the status of flight changes.
For example, we have a flight in departures and the status now is "to gate" but later is "Boarding"
What I would like to achieve is to add a style element like for To gate a color or icon but when boarding a different color and so on. So I would like to change the cell based on what will be the status value.
I don't know how to do that as I'm new to React. I was thinking on the component below on the row/cell of status maybe it is possible to add an if which changes based on the value. Don't know if it possible.
My component looks like this:
class FlightComponent extends React.Component {
render() {
const { data, activeTab } = this.props;
let columns = [
//{ Header: 'Date', accessor: 'date' },
{ Header: 'Time', accessor: 'time' },
{ Header: 'Expected', accessor: 'expected', Cell: (row) => (<div className="expected">{row.value}</div>) },
{ Header: 'Airline', accessor: 'airline', Cell: (row) => (<div className="airline-name">{row.value}</div>) },
{ Header: 'Flight No.', accessor: 'flight_no'},
];
if (activeTab == 1) {
columns.push({ Header: 'Destination', accessor: 'destination' })
} else {
columns.push({ Header: 'Arriving From', accessor: 'arriving_from' })
}
columns = columns.concat([
{ Header: 'Gate', accessor: 'gate' },
{ Header: 'Terminal', accessor: 'terminal' },
{ Header: 'Status', accessor: 'status' }
]);
return (
<div>
<ReactTable
columns={ columns }
data = {this.props.data}
/>
</div>
)
}
}
For react-table you could use Custom Cell, Header and Footer Rendering
You can use any react component or JSX to display content in column headers, cells and footers. Any component you use will be passed the following props (if available):
row - Original row from your data
original - The post-accessed values from the original row
index - The index of the row
viewIndex - the index of the row relative to the current page
level - The nesting depth (zero-indexed)
nestingPath - The nesting path of the row
aggregated - A boolean stating if the row is an aggregation row
subRows - An array of any expandable sub-rows contained in this row
You can check, here is wokring stackblitz demo.
Code Snippet
render() {
const data = [{
task: 'Demo 1',
status: 'pending'
}, {
task: 'Demo 2',
status: 'completed'
}]
const columns = [{
Header: 'Task Name',
accessor: 'task'
}, {
Header: 'Status',
accessor: 'status',
Cell: (row, original, index, viewIndex, level, nestingPath, aggregated, subRows) => {
row.styles['color'] = '#fff';
row.styles['backgroundColor'] = row.value == 'pending' ? 'red' : 'green';
return row.value.toUpperCase();
}
}];
return (
<ReactTable
data={data}
columns={columns}
defaultPageSize={5}
className="-striped -highlight"
/>
);
}

Store calculated data in Column of Kendo Grid

What I'm trying to do is store some data in a specific column that is calculated by using the data from another column.
I currently have a function that returns the number of available licenses for the given Id in JSON
function getAvailableLicenses(id) {
var url = "/Host/Organization/AvailableLicenses/" + id;
$.get(url, function (data) {
return data.AvailableLicenses;
});
}
How do I go about storing this number in a column named "AvailableLicenses"?
Here is my current Grid:
$("#OrganizationGrid").kendoGrid({
dataSource: viewModel.get("orgDataSource"),
filterable: {
extra: false
},
sortable: true,
pageable: true,
columns: [
{ field: "Id", hidden: true },
{ field: "Name", template: "<a href='/Host/Organization/Detail/#:Id#'>#:Name#</a>" },
{ field: "LicenseNumber", title: "Number of Licenses" },
{ field: null, title: "Available Licenses", template: "#= getAvailableLicenses(Id) #" },
{ field: "LicenseExpiration", title: "License Expiration", format: "{0:MM/dd/yyyy}" },
{ field: "State" },
{ field: "Active" }
],
editable: false
});
As you can see, I tried to create a null column with a template that calls the function for the given Id.
By using Fiddler I can see that the function is indeed being called for all of the rows, but the AvailableLicenses column just displays Undefined for every row.
Is there something I'm missing here to get this to work?
I think the better way to do this is on dataSource parse() function
First: you column configuration must change like this:
{ field: "AvalableLicenses", title: "Available Licenses" },
You alaways can use you template .
And second, inside your dataSource() you can add:
schema: {
parse: function(response) {
for (var i = 0; i < response.length; i++) {
response[i].AvalableLicenses= null;
response[i].AvalableLicenses = getAvailableLicenses(response[i].Id)
}
return response;
}
}
EDIT:
If you prefer using you way, I dont see any problem in your configuration, probably your $.get is returning undefined, or something you don't expect.
For conviniance I did an example working.
http://jsfiddle.net/jwocf897/
Hope this help

DGrid Editor - Changing the Displayed Value when Trying to Edit a Text Cell

I'm using a DGrid editor column to edit the contents of a store. Of the fields that I want to be able to edit, one is an object. When I click on the field to edit it, what I want is for the value displayed in the editor to match the value displayed by the grid when not editing. The cell formatting just shows the value of the object, but when I click on the field to edit it, instead of the object's value, I instead the field is populated with '[object Object]'. I can still edit it (though the results of doing so is that the field will display 'undefined' until I refresh the page, but I could just force a refresh after the change), but can't seem to get it to show what I want.
Here's the set up code:
// build the store
this.postStore = Observable(Memory({
data: posts
}));
var formatCategory = function(object, data, cell) {
cell.innerHTML = object.category.value;
};
var formatAuthor = function(object, data, cell) {
cell.innerHTML = object.author.value;
};
var formatDate = function(object, data, cell) {
cell.innerHTML = new Date(object.dateCreated).toISOString();
};
// the columns displayed in the grid
var columns = [
selector({
field: 'checkbox',
label: ' ',
selectorType: 'radio',
width:33
}),
{
label: "Author",
field: "author",
width: 120,
renderCell: formatAuthor
},
editor({
label: "Title",
field: "title",
editor: "text",
editOn: "click",
width: 200
}),
editor({
label: "Text",
field: "text",
editor: "text",
editOn: "click",
width:500
}, Textarea),
editor({
label: "Category",
field: "category",
editor: "text",
editOn: "click",
width: 150,
renderCell: formatCategory
}),
{
label: "Date",
field: "date",
renderCell: formatDate,
width: 120
}
];
if (this.postGrid) {
this.postGrid.set("store", this.postStore);
} else {
var SelectionGrid = new declare([OnDemandGrid, Selection, Keyboard, editor, selector, DijitRegistry, ColumnResizer]);
this.postGrid = new SelectionGrid({
store: this.postStore,
columns: columns,
selectionMode: 'none',
sort: [{attribute: "date", descending: false}]
}, this.postGridDiv);
this.postGrid.startup();
this.postGrid.on("dgrid-select, dgrid-deselect", lang.hitch(this, this._postSelected));
this.postGrid.on("dgrid-datachange", lang.hitch(this, function(evt){
var cell = this.postGrid.cell(evt);
var post = cell.row.data;
if (cell.column.field === "title") {
post.title = evt.value;
} else if (cell.column.field === "text") {
post.text = evt.value;
} else if (cell.column.field === "category") {
post.category.value = evt.value;
}
this._updatePost(post);
}));
Instead of defining a renderCell function, define a get function (which is used to transform the value before it is even sent to renderCell) and a set function (which is used to transform data back before it's sent to a store when saving edits).
Something like:
get: function (object) {
return object.category.value;
},
set: function (object) {
return { value: object.category };
}
See also the documentation.

Categories

Resources