Adding serial number column in the table - reactjs

I am using a library named react-data-table-component for table in my application. Everything is going pretty smooth however I need to add a column which will show serial number in my table. The serial number will always start from 1 to total number of objects in photos array.
const columns = [
{
name: '#',
selector: 'id',
cell: (row) => <span>{I need to show serial number here}</span>
},
{
name: 'Name',
selector: 'photo_link',
sortable: true,
}
... // Other fields
]
<DataTable
columns={columns}
data={photos}
paginationTotalRows={total_photos}
Cell key inside column array just takes row as argument and it has current object but I can't get the index of object.
I have the id field in every object of the array but that is not in sequence which I need. How do I solve this problem?

I think the easiest way is to add the serial number to your array items upfront.
photos.forEach((photo, index) => { photo.serial = index + 1; });
Then, simply use this serial field in your columns definition:
{
name: '#',
selector: 'serial'
}

I know it's late, but posting as it would help others!
You can have a serial number with the help of index in your column definition, for example
const columns = [
{
name: '#',
cell: (row, index) => index + 1 //RDT provides index by default
},
... // Other fields
]
And indexes start with 0 always, so we are using + 1, Now it will start with 1.

Try this in columns
render:(text,record,index)=>`${index+1}`,

You were almost there.
I used below code to get the desired outcome, We can avoid adding new field ('serial' as suggested by Zord) to objects in the array.
Cell: (props) => (<span>{props.index + 1}</span>)

Related

Sorting capability linked to only one column at a time using react

I came across this code which enables sorting to just one column at a time. When I using sorting buttons on first column, it works fine! But as soon as I click on sorting arrows of the second column, the arrows disappear from the first column. I am trying to debug it but unable to do so. Below is the code that constructs the grid header and applies sorting functionality.
function createGridHeaders(gridData, onSort) {
const sortInfo = gridData.getSortInfo();
const sortId = sortInfo ? sortInfo.getColumnId() : undefined;
return gridData
.getHeaders()
.map(id => ({
headerName: new FieldRef(id, getGlobal).getLabel(),
field: id,
cellRendererParams: { format: getCellFormatter(new FieldRef(id, getGlobal)) },
resizable: true,
headerComponentParams: {
sortOrder: 'asc'
},
onSort
}));
}
onSort(sortInfo) {
this.setState({
gridData: this.state.gridData.setSortInfo(sortInfo)
});
}
My grid looks like :
Based on the data, the label and content is filled. Why would sorting capability be linked to a particular column ?

How to set unique id by row and column to Antd table input fields?

Currently I'm trying to build an input based table
const columns = [{
title: 'Items',
dataIndex: `Items`,
key:`Items`
}];
Then I loop thru an array for the rest of the columns that are for checkbox
countryList.forEach((id) => {
const data = CountryDetail[id].name;
columns.push({
title: data,
dataIndex: data,
key: data,
render: (value, rowId) => (
<Checkbox
checked={value}
...
)
})
});
The datasource will be dynamically generated as well. Since I need to get the boolean values from the checkboxes, is there a way to give all checkbox unique id for identification for submission? I had tried creating with function but since it is in class component, usestate could not be used.
const data = [{
Items: 'Chips',
Japan: true,
...
}]

Antd design table column -> how to pass array of objects to dataIndex

I'm fetching object (contract) from DB, it contains few fields, one of them is an array of objects (products). I have antd table with column Products and I would like to fill it with product names.
For example, my contract object also has account object, and the way I use dataIndex there is like this:
{
title: 'Account',
dataIndex: ['account', 'name'],
key: 'account',
align: 'center',
sorter: (a, b) => a.length - b.length
}
That works fine! But Account is not an array.
Here is code with issue:
{
title: 'Products',
dataIndex: ['products'],
key: 'products',
align: 'center',
filters: []
}
Here is how I map data that is send to component above which has to fill table:
return data.map((contract) => ({
key: contract._id,
account: contract.account,
products: [contract.products],
}));
I tried returning just contract.products, tried returning Object.values(contract.products), tried to JSON.stringify(contract.products) but then I don't know how to parse it in column and take just name...
The only way I managed to set name was by not sending object. Example:
return data.map((contract) => ({
key: contract._id,
account: contract.account,
products: contract.products.map(product => product.name),
}));
This would indeed solve this problem, but it would made me make another asyncThunk method where I would return whole array of objects.
Hope that I described that well,this is for my college project and it's bean bugging me whole day.
I would be very grateful if someone knows how can I solve this.
According to Antd documentation for column dataIndex, it will only accept a string or an array of strings for nested paths.
dataIndex - Display field of the data record, support nest path by string array - string | string[ ]
So I don't think you can pass an array of objects to dataIndex.
The only way around that I can think of would be to convert the array to a string before passing it to your table.
To do that you can use .join() method to add space and a comma between your array items.
const convertArrayToString = (array) => array.join(', ');
And before returning you could use the above function: Example:
return data.map((contract) => ({
key: contract._id,
account: contract.account,
products: convertArrayToString(contract.products),
}));

React Datagrid with cards instead of columns?

We love the DataGrid for its build in sorting and filtering capabilities.
However grid based layouts are troublesome on small screen devices. So we started looking at Card based layouts. There we miss the sorting and filtering we appreciate in the DataGrid.
Now we are wondering if there is an example to use cards as UI layer for the DataGrid, where a column in the grid would become a row in the card. Cards should flow to available columns.
How can we do this?
This is a partial answer, however, there is a renderCell prop in the column configuration that accepts a function that can include a component.
So, to replace a row with a card, I might include a column that renders your components with all of the values you would otherwise express one by one in a series of columns. For instance:
const columns = [
{ field: 'id', headerName: 'ID', hide: true }, // keep this
{ field: 'myCombinedView', hide: false, flex: 1, renderCell: (props) => <Component {...props} /> },
I can imagine including a single, hidden column that represents a concatenation of the values you want to sort on. From here, specify the sort function for the Component column that uses the hidden value.
The following code sample is pulled from the DataGrid storyboard:
() => {
const columns = getColumns();
// compute a new field for purposes of sorting
columns[columns.length] = {
field: 'username',
valueGetter: (params) =>
`${params.getValue('name') || 'unknown'}_${params.getValue('age') || 'x'}`,
sortComparator: (v1, v2, cellParams1, cellParams2) => cellParams1.row.age - cellParams2.row.age,
width: 150,
};
return (
<div className="grid-container">
<XGrid
rows={getRows()}
columns={columns}
// use the field as the sort model
sortModel={[{ field: columns[columns.length - 1].field, sort: 'asc' }]}
/>
</div>
);
}
How to dynamically select/change the sort criteria is not something I can see a clear path for.

How to set value for additional column in pivot table in OctoberCMS?

I have doctor and specialization table, and have doctor_specialization_pivot table. In my pivot table I have the following columns:
| doctor_id | additional_data | specialization_id |
additional_data is from the doctor model along with the doctor_id.
In my doctor model file, I have this relationship:
public $belongsToMany = [
'specialization' => [
'path\to\specialization\model',
'table' => 'doctor_specialization_pivot',
'parentKey' => 'doctor_id',
'otherKey' => 'specialization_id',
]
];
Now during submit of form, I'm getting this error:
SQLSTATE[HY000]: General error: 1364 Field 'additional_data' doesn't have a default value (SQL: insert into doctor_specialization_pivot (doctor_id, specializations_id) values (1, 3))"
I tried adding to my relationship 'pivot' => ['additional_data']. But still getting the same error.
I checked the submitted data and additional_data is not empty. I checked from OctoberCMS forums but not getting straight forward answers such as this and this.
Okay. I found the answer to my own question.
I'll answer in detail to help everyone. After digging and blind shooting. According to this documentation here, we can use the method attach() to attach a role to a user by inserting a record in the intermediate table that joins the models.
What confuse me in the documentation is that it uses a $roleId variable and I didn't understand where the $roleId came from. If it's the id of the parent table or the id of other table.
Sample from the link:
$user = User::find(1);
$user->roles()->attach($roleId);
So what I did in my doctor model, I hook to the event beforeSave, use the relationship ($this->specialization) as the first parameter instead of the id in the docs. The $this->specialization() is the relationship too defined in belongsToMany.
Answer:
public function beforeSave()
{
$this->specialization()->attach($this->specialization,['additional_data' => 'additional data from doctor table']);
}
The implementation is pretty much like this video from Watch Learn (Ivan). You can learn a lot about OctoberCMS just by watching his guide on it. Here is the documentation on it as well. This is the example info that I have done.
WARNING Another known flaw is you can't apply this to a model record that isn't created yet. Unlike the standard relation widget which waits until it is saved before attaching records this attaches records in a separate overlay form.
Here is my model.php relationship:
public $belongsToMany = [
'equipments' => [
'Brandon\Pixelrpg\Models\Equipments',
'table' => 'brandon_pixelrpg_equipment_inventory',
'key' => 'inventory',
'otherKey' => 'equipment',
'pivot' => ['quantity']
]
];
Here is my controller.php:
public $implement = [
'Backend\Behaviors\ListController',
'Backend\Behaviors\FormController',
'Backend\Behaviors\ReorderController',
'Backend\Behaviors\RelationController'
];
public $listConfig = 'config_list.yaml';
public $formConfig = 'config_form.yaml';
public $reorderConfig = 'config_reorder.yaml';
public $relationConfig = 'config_relation.yaml';
Here is my config_relation.yaml:
equipments:
label: Equipments
view:
list:
columns:
id:
label: ID
type: number
searchable: true
sortable: true
name:
label: Name
type: text
searchable: true
sortable: true
value:
label: Value
type: number
searchable: true
sortable: true
updated_at:
label: Updated
type: datetime
searchable: true
sortable: true
pivot[quantity]:
label: Quantity
type: number
pivot:
form:
fields:
pivot[quantity]:
label: Quantity
type: number
default: 0
I am just going to make a new answer and assume is what you need because you have yet to show any code on how your form works. This is how I would update the pivot information from a frontend form.
Relationship in model.php:
public $belongsToMany = [
'specialization' => [
'path\to\specialization\model',
'table' => 'doctor_specialization_pivot',
'parentKey' => 'doctor_id',
'otherKey' => 'specialization_id',
'pivot' => ['additional_data'] //This is required
]
];
Then in some php code lets call it onAddSpecialization():
public function onAddSpecialization() {
//Calling a function to get the doctor id maybe from the signed in user
$doctor = Doctors::find($this->$doctorId());
//We get our Specialization from an input
$specialization = Specialization::find(Input::get('specialization_id'));
//We get our additional data from an input
$additional_data = Input::get('additional_data');
//Now we are going to attach the information
$doctor->specialization()->attach($specialization, ['additional_data' => $additional_data]);
}
Now an example of updating our additional data:
public function onUpdateAdditionalData() {
//Calling a function to get the doctor id maybe from the signed in user
$doctor = Doctors::find($this->$doctorId());
//If you get specialization by id from an input. I believe you need to go through the relationship in order to access the correct pivot information.
$specialization = $doctor->specialization->where('id', Input::get('specialization_id'))->first();
//Insert the new pivot information
$specialization->pivot->additional_data = $new_additional_data;
//Save
$specialization->pivot->save();
}

Resources