I created table with ant design ProTable Component and its Edit function is not working. It showing error like this. ("Cannot read properties of undefined (reading 'toString')"). I tried many ways to solve this problem and cannot found a solution yet.
I want get table data from CSV file upload. That function is already working and data retrieved to the table.
const columns = [
{
title: 'First Name',
valueType: 'string',
typeof:'string',
dataIndex: 'fName',
formItemProps: () => {
return {
rules: [{ required: true, message: '' }],
};
},
},
{
title: 'Last Name',
valueType: 'string',
typeof:'string',
dataIndex: 'lName',
formItemProps: () => {
return {
rules: [{ required: true, message: '' }],
};
},
},
{
title: 'Email',
valueType: 'string',
typeof:'string',
dataIndex: 'email',
formItemProps: () => {
return {
rules: [{ required: true, message: '' }],
};
},
},
{
title: 'Position',
valueType: 'string',
typeof:'string',
dataIndex: 'position',
formItemProps: () => {
return {
rules: [{ required: true, message: '' }],
};
},
},
{
title: 'Actions',
valueType: 'option',
width: 200,
render: (text, record, _, action) => [
<a
key="delete"
onClick={() => {
setData(data.filter((item) => item.id !== record.id));
}}
>
Delete
</a>,
<a
key="editable"
onClick={() => {
var _a;
(_a = action === null || action === void 0 ? void 0 : action.startEditable) === null ||
_a === void 0
? void 0
: _a.call(action, record.id);
}}
>
Edit
</a>,
],
},
];
EditableProTable
rowKey="id"
actionRef={actionRef}
headerTitle=""
maxLength={5}
recordCreatorProps={false}
columns={columns}
request={async () => ({
data: data,
total: 3,
success: true,
})}
value={csvArray}
onChange={setCsvArray}
editable={{
type: 'multiple',
editableKeys,
onSave: async (rowKey, data, row) => {
await waitTime(2000);
},
onChange: setEditableRowKeys,
actionRender: (row, config, defaultDom) => [
defaultDom.save,
defaultDom.delete || defaultDom.cancel,
],
}}
/>[![enter image description here][1]][1]
The editableKeys array contains rows that are in the editing state
const [editableKeys, setEditableRowKeys] = useState(() => csvArray.map((item) => item.index)); // or .map((item=) => item.key));
Related
I'm facing an issue while keeping a row focused/selected in AG Grid. I'm expecting it to be highlighted/selected even after I do certain actions like API calls, Does anyone know what is the fix?
This is my AGGridComponent
<CustomAgGrid
ref={gridRef}
animateRows={false}
filter={false}
className="ag-theme-balham charity-grid"
columnDefs={[
{
field: 'num',
headerName: 'Num',
width: 58, //53 + 17
},
{
field: 'campaignName',
headerName: 'Campaign Name',
width: 151,
},
{
field: 'description',
headerName: 'Description',
width: 140,
},
{
field: 'isActive',
headerName: 'Status',
width: 110, //53 + 17
cellRenderer: 'StatusIndicator',
},
]}
detailCellRenderer=""
frameworkComponents={{
exceptionMessage: function noRefCheck() {},
StatusIndicator: StatusIndicator,
}}
masterDetail={false}
noRowsOverlayComponent=""
noRowsOverlayComponentParams={{
messageHeader: '',
messageInfo: ['No data to display'],
messageType: 'info',
}}
rowData={campaignDataClone}
context={{ gridApi }}
rowSelection="single"
onGridReady={onGridReady}
onSelectionChanged={onSelectionChanged}
onFirstDataRendered={onFirstDataRendered}
/>
These are grid event handler
const onGridReady = params => {
params.api.sizeColumnsToFit();
window.addEventListener('resize', function() {
setTimeout(function() {
params.api.sizeColumnsToFit();
});
});
gridRef.current.api.sizeColumnsToFit();
setGridApi(params.api);
};
const onFirstDataRendered = () => {
const rows = gridRef.current.api.clientSideRowModel.rowsToDisplay;
if(rows?.length){
rows[0].setSelected(true);
setGridLoaded(true)
}
};
This is how i dispatch actions to perform an API request
buttons={[
{
buttonLabel: 'No - Go Back',
className: `btn-secondary btn-lg btn-block`,
onClick: () => {
toggleCampaignStatusConfirm(false);
const selectedRows = gridRef.current.api.getSelectedRows();
toggleCampaignEnable(selectedRows[0]?.isActive ? 'first_toggle' : 'second_toggle');
},
},
{
buttonLabel: `${isActive ? 'Yes - Disable' : 'Yes - Enable'}`,
className: `${isActive ? 'btn-danger' : 'btn-success'} btn-lg btn-block`,
onClick: () => {
toggleCampaignStatusConfirm(false);
dispatch(changeCampaignStatus(selectedCampaign?.campaignId, !isActive));
},
},
]}
Once the API requests are done it just updates the redux and the component will be rendered. Here I'm expecting it to maintain the focus and the row should be selected. Can anyone please help me with how to achieve/fix this?
first please my javascript skill level is not good, but here... I have a table i got from ant.design, im trying to build a frontend with react, so I want to display some data on the table from my database but im finding it had because of the want ant design table is set up.
This is the code
class OrderSummary extends React.Component {
state = {
data: null,
error: null,
loading: false
};
componentDidMount() {
this.handleFetchOrder();
}
handleFetchOrder = () => {
this.setState({ loading: true });
authAxios
.get(orderSummaryURL)
.then(res => {
this.setState({ data: res.data, loading: false });
})
.catch(err => {
// if (err.response.status === 404) {
// this.setState({
// error: "You currently do not have an order",
// loading: false
// });
// } else {
this.setState({ error: err, loading: false });
// }
});
};
render() {
const columns = [
{
title: 'Number',
dataIndex: 'number',
key: 'number',
render: text => <a>{text}</a>,
},
{
title: 'Event Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Event Price',
dataIndex: 'price',
key: 'price',
},
{
title: 'Quantity',
dataIndex: 'quantity',
key: 'quantity',
},
{
title: 'Total',
dataIndex: 'total',
key: 'total',
},
];
const datasource =
{data.order_items.map((orderItem, i) => {
return (
[
{
key: {orderItem.id},
number: {orderItem.item.title} -{" "},
name: 32,
price: 'NGN' {orderItem.item.price} ,
quantity: {orderItem.quantity},
total: {data.total},
},
// {
// key: 1,
// name: 'John Brown',
// age: 32,
// address: 'New York No. 1 Lake Park',
// tags: ['nice', 'developer'],
// },
];
return (
<Layout>
<div>
<PageHeader
className="site-page-header"
onBack={() => null}
title="Order Summary"
/>
<Table columns={columns}
dataSource={datasource} />
</div>
</Layout>
)
}
};
export default OrderSummary;
Note where i commented out, that part works perfectly because thats how it comes from ant.design
This is the error I keep getting
Failed to compile
./src/containers/OrderSummary.js
Line 95:14: Parsing error: Unexpected token, expected ","
93 |
94 | const datasource =
> 95 | {data.order_items.map((orderItem, i) => {
| ^
96 | return (
97 | [
98 | {
Please help.
First
It seems you didn't close correctly your datasource.
After your ] you need ) } ) } ;
Second
You have to add order_items in data in the state, as it's null and handleFetchOrder is asynchronous. At the time you want to render it will create an error because you try to iterate over a no existing property.
Here a example of what you can try:
In your state declaration:
state = {
data: {
order_items: []
},
error: null,
loading: false
};
In your render function:
Add a const to get your state value:
const data = this.state.data;
const datasource = { data.order_items.map((orderItem, i) => { ... })};
I am using Datatables to display a table and I am pulling a list of datestimes from a MySQL database. These date times are not standard dates and look like this:
12/30/19 # 04:17 pm
How can I sort these accurately with Datatables?
Here is my code:
getRes(function (result) { // APPLIED CALLBACK
$('#resdatatable').DataTable({
data: result, // YOUR RESULT
order: [[ 0, "desc" ]],
autoWidth: false,
responsive: true,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'bookingdatetime', title: 'Booking Date' },
{ data: 'name', title: 'Name' },
{ data: 'class', title: 'Class' },
{ data: 'pickupdatetime', title: 'Pick up' },
{ data: 'duration', title: 'Duration' },
{ data: 'dropdatetime', title: 'Drop off' },
{ data: 'age', title: 'Age' },
{ data: 'coverage', title: 'Coverage' },
{ data: 'quote', title: 'Quote' },
{
data: 'status',
title: 'Status',
render: function(data, type, row) {
let isKnown = statusList.filter(function(k) { return k.id === data; }).length > 0;
if (isKnown) {
return $('<select id="resstatus'+row.id+'" onchange="changeResStatus('+row.id+')" data-previousvalue="'+row.status+'">', {
id: 'resstatus-' + row.id, // custom id
value: data
}).append(statusList.map(function(knownStatus) {
let $option = $('<option>', {
text: knownStatus.text,
value: knownStatus.id
});
if (row.status === knownStatus.id) {
$option.attr('selected', 'selected');
}
return $option;
})).on('change', function() {
changeresstatus(row.id); // Call change with row ID
}).prop('outerHTML');
} else {
return data;
}
}
}
]
});
});
/**
* jQuery plugin to convert text in a cell to a dropdown
*/
(function($) {
$.fn.createDropDown = function(items) {
let oldTxt = this.text();
let isKnown = items.filter(function(k) { return k.id === oldTxt; }).length > 0;
if (isKnown) {
this.empty().append($('<select>').append(items.map(function(item) {
let $option = $('<option>', {
text: item.text,
value: item.id
});
if (item.id === oldTxt) {
$option.attr('selected', 'selected');
}
return $option;
})));
}
return this;
};
})(jQuery);
// If you remove the renderer above and change this to true,
// you can call this, but it will run once...
if (false) {
$('#resdatatable > tbody tr').each(function(i, tr) {
$(tr).find('td').last().createDropDown(statusList);
});
}
function getStatusList() {
return [{
id: 'Confirmed',
text: 'Confirmed'
}, {
id: 'Unconfirmed',
text: 'Unconfirmed'
}, {
id: 'Communicating',
text: 'Communicating'
}, {
id: 'Open',
text: 'Open'
}, {
id: 'Closed',
text: 'Closed'
}, {
id: 'Canceled',
text: 'Canceled'
}, {
id: 'Reallocated',
text: 'Reallocated'
}, {
id: 'No Show',
text: 'No Show'
}];
}
I need to sort bookingdatetime, pickupdatetime, dropdatetime accurately (they are currently being converted into MM/DD/YY in the PHP script)
Maybe you can prepend hidden <span> elements containing the respective unix timestamps in the cells that have dates (by manually parsing the dates). Then using such columns to sort alphabetically would practically sort time-wise.
I am using Vue 2
I am displaying a table using datatable using Vuetify.
For each row I need to show a button on click of which a function will get called.
I tried #click and v-on:click both of which did not work. It complains about syntax error on this line.
Can someone please guide me how to do it ?
The error is in map function in detail key:
this.calls = calls.data.result.calls
.map((obj, i) => ({
id: obj.id,
createAt: moment.parseZone(obj.created_at).format('YYYY-MM-DD hh:mm a'),
startTime: (obj.start_time) ? moment.parseZone(obj.start_time).format('YYYY-MM-DD hh:mm a') : '',
username: obj.User.username.toUpperCase(),
expertName: obj.Expert.expertName.toUpperCase(),
status: CALL_STATUS[obj.status],
detail: (obj.status !== 'complete' && obj.status !== 'cancel') ? <v-btn v-on:click="callSomeFunction(id)">Change Status</v-btn>:'', // Error is on this line
}));
My code is :
<template>
<div>
<v-data-table
:headers="headers"
:items="calls"
:hide-default-footer="true"
class="elevation-1"
></v-data-table>
<v-pagination v-if="this.pagination.total > 0"
v-model="pagination.current"
:length="pagination.total"
:total-visible=10
#input="onPageChange"
></v-pagination>
</div>
</template>
<script>
import moment from 'moment';
import callAPI from '#/api/CallAPI';
import { CALL_STATUS } from '../../constants/enum';
export default {
name: 'listing',
props: ['dates', 'status'],
mounted() {
this.loadCalls();
},
watch: {
dates() {
this.pagination.current = 1;
this.pagination.total = 0;
this.pagination.offset = 0;
this.loadCalls();
},
status() {
this.pagination.current = 1;
this.pagination.total = 0;
this.pagination.offset = 0;
this.loadCalls();
},
},
data() {
return {
headers: [
{
text: 'Call Id',
align: 'left',
sortable: false,
value: 'id',
},
{ text: 'Booking Time', sortable: false, value: 'createAt' },
{ text: 'Confirmed Time', sortable: false, value: 'startTime' },
{ text: 'User name', sortable: false, value: 'username' },
{ text: 'Expert name', sortable: false, value: 'expertName' },
{ text: 'Status', sortable: false, value: 'status' },
{ text: 'Detail', sortable: false, value: 'detail' },
],
search: '',
pagination: {
current: 1,
total: 0,
perPage: 20,
offset: 0,
},
resizable: true,
adaptive: true,
draggable: true,
calls: [],
};
},
methods: {
show () {
this.$modal.show('example-modal')
},
hide () {
this.$modal.hide('example-modal')
},
async loadCalls() {
const date1 = moment(`${this.dates[0]} 00:00:00`).format('x');
const date2 = moment(`${this.dates[1]} 23:59:59`).format('x');
console.log(`${this.dates[0]} 00:00:00`, date1, `${this.dates[1]} 23:59:59`, date2);
const calls = await callAPI.getListing(
{
startTime: date1,
endTime: date2,
status: this.status,
limit: this.pagination.perPage,
offset: this.pagination.offset,
},
);
this.calls = calls.data.result.calls
.map((obj, i) => ({
id: obj.id,
createAt: moment.parseZone(obj.created_at).format('YYYY-MM-DD hh:mm a'),
startTime: (obj.start_time) ? moment.parseZone(obj.start_time).format('YYYY-MM-DD hh:mm a') : '',
username: obj.User.username.toUpperCase(),
expertName: obj.Expert.expertName.toUpperCase(),
status: CALL_STATUS[obj.status],
detail: (obj.status !== 'complete' && obj.status !== 'cancel') ? <v-btn v-on:click="callSomeFunction(id)">Change Status</v-btn>:'', // Error is on this line
}));
if (this.calls.length > 0) {
this.pagination.current = calls.data.result.currentPage;
}
this.pagination.total = calls.data.result.totalPage;
console.log(this.calls);
},
onPageChange(number) {
this.pagination.offset = (number > 1) ? ((number * this.pagination.perPage) - this.pagination.perPage) : 0;
this.loadCalls();
},
},
};
</script>
this.calls = calls.data.result.calls
.map((obj, i) => ({
id: obj.id,
createAt: moment.parseZone(obj.created_at).format('YYYY-MM-DD hh:mm a'),
startTime: (obj.start_time) ? moment.parseZone(obj.start_time).format('YYYY-MM-DD hh:mm a') : '',
username: obj.User.username.toUpperCase(),
expertName: obj.Expert.expertName.toUpperCase(),
status: CALL_STATUS[obj.status],
detail: (obj.status !== 'complete' && obj.status !== 'cancel') ? '<v-btn v-on:click="callSomeFunction(id)">Change Status</v-btn>' :'', // Error is on this line
}));
try to add '' for your html
Currently I have created a component that wraps BootstrapTable. I have to define a constant that represents the columns of data. But, the way I have it right now seems to really clutter up my render method. I'd like to move it to its own file, but I'm not sure the best way to do this, because it requires callbacks that are defined in the class (notably the onUpdateClicked method).
If the way I have it is a fine way of doing things, that would be good to know. But, assuming I did want to move it to another file regardless, suggestions would be appreciated for my own edification. Thanks!
class MyTable extends Component {
onUpdateClicked() {
//do stuff
}
render() {
let {data} = {...this.props}
let columns = [
{
dataField: 'badge',
text: 'Badge',
sort: true
}, {
dataField: 'firstName',
text: 'First',
sort: true
}, {
dataField: 'lastName',
text: 'Last',
sort: true
}, {
dataField: 'email',
text: 'Email',
sort: true
}, {
dataField: 'loggedIn',
text: 'Logged In',
sort: true,
formatter: (cell, row) => {
if (row.loggedIn) {
return (<FontAwesomeIcon icon="check"/>)
}
}
}, {
dataField: 'update',
text: 'Update',
formatter: () => {
return (<Button onClick={this.onUpdateClicked} color="primary">Update</Button>)
}
},
];
return (
<div>
<BootstrapTable Bootstrap4 keyField='badge' data={data} columns={columns}/>
</div>
)
}
}
you can put the columns in a seperate file, but export a function that takes a function as a parameter to be used for the onClick
Columns.js
const columnsFn = someFunc => ([ // pass the function as a param.
{
dataField: 'badge',
text: 'Badge',
sort: true
}, {
dataField: 'firstName',
text: 'First',
sort: true
}, {
dataField: 'lastName',
text: 'Last',
sort: true
}, {
dataField: 'email',
text: 'Email',
sort: true
}, {
dataField: 'loggedIn',
text: 'Logged In',
sort: true,
formatter: (cell, row) => {
if (row.loggedIn) {
return (<FontAwesomeIcon icon="check"/>)
}
}
}, {
dataField: 'update',
text: 'Update',
formatter: () => {
return (<Button onClick={someFunc} color="primary">Update</Button>) // use it here
}
},
]);
export default columnsFn;
YourFile.js
import columnsFn from './columns';
class MyTable extends Component {
onUpdateClicked() {
//do stuff
}
render() {
const {data} = {...this.props}
const myColumns = columnsFn(this.onUpdateClicked); // pass the function here
return (
<div>
<BootstrapTable Bootstrap4 keyField='badge' data={data} columns={myColumns}/>
</div>
)
}
}