React.js: table inside expandable rows - javascript

I have an antd expandable rows table with vehicles. I want to display in the expanded row all the bookings of the specific vehicle.
This is the vehicles table with its datasource:
const vehiclesData = (
props.vehicles.map(vehicle =>{
addMonths(2,vehicle.insuranceStart);
return {
"key":vehicle.id,
"brand":vehicle.brand !=null ? vehicle.brand.brand : '',
"model":vehicle.model !=null ? vehicle.model.model : '',
"color":vehicle.color,
"plate":vehicle.plate,
"insuranceStart":moment(vehicle.insuranceStart).format('DD/MM/YYYY'),
"insuranceType":vehicle.insuranceType !=null ? vehicle.insuranceType.company + ' ('+vehicle.insuranceType.duration +' Μήνες'+')' : '',
"brand_id":vehicle.brand !=null ? vehicle.brand.id : '',
"model_id":vehicle.model !=null ? vehicle.model.id : '',
"insurance_id":vehicle.insuranceType !=null ? vehicle.insuranceType.id : '',
"bookings": vehicle.bookings != null ? vehicle.bookings : ''
}
})
)
<Table
expandedRowRender={record => <p style={{ margin: 0 }}>{record.bookings}</p>}
dataSource={vehiclesData}
size="small"
bordered
columns = {columns}
loading={props.vehiclesLoading!=null ? props.vehiclesLoading : false}
/>
This is what I have tried so far which obviously doesn't work. I was thinking that I can replace <p style={{ margin: 0 }}>{record.bookings}</p> with another table but I don't know how I can configure the child's table datasource in order to fetch only the bookings of the expanded row's vehicle.

You can pass another <Table dataSource={record.bookings} /> like you suggested to the expandableRowRender with new column names.
Here's a sample code box that I edited from the example on the AntD documentation.
https://codesandbox.io/s/compassionate-microservice-4z5gq
Hope that helps

Related

Access Ant Design table column value

I am trying to condionally render Bage based on status column value. Even though I can render the table with the status values, I cannot access the status column for each item for conditional rendering of status Badge. How do I access the values listed on the column ?
The "status" value is inside data [ ]
const tableColumns = columns.map((item) => ({
...item,
ellipsis,
}));
const columns = [
{
title: 'Статус',
dataIndex: 'status',
render: () => {dataIndex.status === "in progress" ? <Badge status="processing" text="in progress" /> : <Badge status="success" text="delivered" />}
},
]
<Table
{...tableProps}
pagination={{
position: [top, bottom],
}}
columns={tableColumns}
dataSource={hasData ? data : []}
scroll={scroll}
/>

How can I make a difference on only one card when I make a card list by map function with React?

I want to make cards list like the 'Goal' picture. If you look at first picture, last card has only difference at price and last part. But I don't know how to make difference when I use array and map function. Should I resolve it by using conditional rendering? If I could, please let me know how to make it. I'd appreciate it if you let me know thank you.
Goal
Mine
this is Section5Bottom.jsx file. There are array and map function in this file. I erased 'people' element in last array but css still remains so it still shows little pink background-color like 'Mine' picture above
import React from 'react';
import "../section5.css";
import Section5Card from './Section5Card';
const array = [
{
'id' : '1',
'img' : "https://cdn.inflearn.com/public/courses/324119/course_cover/07c45106-3cfa-4dd6-93ed-a6449591831c/%E1%84%80%E1%85%B3%E1%84%85%E1%85%AE%E1%86%B8%205%20%E1%84%87%E1%85%A9%E1%86%A8%E1%84%89%E1%85%A1%204.png",
'title' : '실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발',
'name' : '김영한',
'star' : '5',
'comment' : '(1473)',
'price' : '₩88,000',
'people' : '+12400명',
},
{
'id' : '1',
'img' : "https://cdn.inflearn.com/public/courses/324671/course_cover/638eee1a-6381-402d-a17b-3724751414f1/frontend-env-eng.png",
'title' : '프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..)',
'name' : '김정환',
'star' : '5',
'comment' : '(169)',
'price' : '₩69,300',
'people' : '+2000명',
},
{
'id' : '1',
'img' : "https://cdn.inflearn.com/public/courses/329477/cover/80fb90fb-0212-4eec-8fb0-7875622b198e/329477-eng.png",
'title' : '애플 웹사이트 인터랙션 클론!',
'name' : '1분코딩',
'star' : '5',
'comment' : '(187)',
'price' : '₩77,000',
'people' : '+3200명',
},
{
'id' : '1',
'img' : "https://cdn.inflearn.com/public/courses/327193/cover/010c8faf-bfc5-4c6a-9623-a68dc3b38697/327193-eng.png",
'title' : 'Slack 클론 코딩[백엔드 with NestJS + TypeORM]',
'name' : '조현영',
'star' : '4.5',
'comment' : '(58)',
'price' : '₩44,000',
'people' : '+1100명',
},
{
'id' : '5',
'img' : "https://cdn.inflearn.com/public/courses/329477/cover/80fb90fb-0212-4eec-8fb0-7875622b198e/329477-eng.png",
'title' : '모바일 웹 퍼블리싱 포트폴리오 with Figma',
'name' : '코딩웍스(Coding Works)',
'star' : '0',
'comment' : '(0)',
'discount' : '₩132,000',
'price' : '₩92,400',
'new' : '새강의',
'sale' : '할인중'
}
]
function Section5Bottom() {
return (
<div id='Section5Bottom'>
{
array.map((a, i) => {
return (
<Section5Card products={a} key={i} />
)
})
}
</div>
)
}
export default Section5Bottom;
and this is Section5Card.jsx file. This file is imported to Section5Bottom.jsx file
import React from 'react';
import '../section5.css';
function Section5Card(props) {
return (
<div id='Section5Card'>
<img src={props.products.img} id="Section5CardImg" />
<div id='Section5CardTitle'>
{props.products.title}
</div>
<div id='Section5CardName'>
{props.products.name}
</div>
<div id='Section5CardComment'>
{props.products.comment}
</div>
<div id='Section5CardPrice'>
{props.products.price}
</div>
<div id='Section5CardPeople'>
{props.products.people}
</div>
{
props.products.new && (
<div id='Section5CardNew'>
{props.products.new}
</div>
)
}
{
props.products.sale && (
<div id='Section5CardSale'>
{props.products.sale}
</div>
)
}
</div>
)
}
export default Section5Card;
function:
const ConditionalWrapper = ({ children, condition }) => {
return condition ? (
<div>{discount price}</div>
) : (
<>{price}</>
)
}
how to use above function
<ConditionalWrapper condition={condition}>children</ConditionalWrapper>
According to the above problem. you should apply condition if discount price avaliable. if true change css for price. I mean text to gray & strike decoration. Add discount price afterward. if false return price with no additional css. like it is in the picture. I'm not fluent in English. I hope you understood. Still facing problem comment

Display row data of all columns upon selecting row or checkbox in MUI datatable

I have a MUI datatable. The properties are defined as follows
data={serialsList || []}
columns={columns}
options={{
...muiDataTableCommonOptions(),
download: false,
expandableRowsOnClick: false,
search: false,
page: currentPage,
rowsPerPage: numberOfRows,
count: serialsTotalCounts,
selectableRows: this.state.cancelShipFlag ? 'multiple' : 'none',
selectableRowsHeader: this.state.cancelShipFlag ? true : false,
selectToolbarPlacement: 'none',
onRowSelectionChange(currentRowsSelected, allRowsSelected, rowsSelected?) {
console.log(currentRowsSelected, allRowsSelected, rowsSelected);
},
//selectableRowsHideCheckboxes: this.state.cancelShipFlag ? true : false,
onRowClick: (rowData, rowMeta) => console.log('onRowsSelect.', rowData, rowMeta),
I want to display the entire row contents as a Json or string if I select a particular row or a checkbox in that row. How do I do this?
I have read that we can use
getSelectedRows: () => Map<GridRowId, GridRowModel>
But i am not sure how to use it. Can someone guide me in this?
I have also seen this link for reference but not sure if it will work
Sandbox example
According by your example
// State for selected rows
const [selectedRows, setSelectedRows] = useState([]);
// Save selected rows to state
onRowSelectionChange: (currentSelect, allSelected) => {
setSelectedRows(allSelected);
}
// return as a JSON
<pre style={{ fontSize: 10 }}>
{JSON.stringify(selectedRows, null, 4)}
</pre>

One input field, different name and validation react hook form

I have a form created with React hook form and input field thant can have 2 different values: a pec email or a SDI code with different validation.
I get error with validation: keep telling me that sdi should be 7 characters but the name is set to "pecEmail". Also at page load "name" is set to "sdiCode" but if an email is already there, should be "email". It changes when I click the input.
I tried to pass the name field in register but I lost all the validation
ref={register(isPec ? 'pecEmail' : 'sdiCode', {
code here:
const [isPec, setIsPec] = useState()
const sdiOrPec = watch(['sdiCode', 'pecEmail'])
useEffect(() => {
setIsPec(
(sdiOrPec.sdiCode && sdiOrPec.sdiCode.includes('#')) ||
(sdiOrPec.pecEmail && sdiOrPec.pecEmail.includes('#'))
)
}, [watch])
<div className='input-container'>
<div
className={`input-container__item ${
errors[isPec ? 'pecEmail' : 'sdiCode'] && 'has-error'
}`}
>
<label>{t('components.BillingInfoForm.sdiLabel')}</label>
<input
type='text'
name={!isPec ? 'sdiCode' : 'pecEmail'}
defaultValue={
get(billingInformations, 'sdiCode')
? get(billingInformations, 'sdiCode')
: get(billingInformations, 'pecEmail')
? get(billingInformations, 'pecEmail')
: ''
}
placeholder={t('components.BillingInfoForm.sdiPlaceholder')}
ref={register({
maxLength: {
value: isPec ? 320 : 7,
message:
!isPec &&
t('components.BillingInfoForm.sdiMessageError'),
},
minLength: {
value: isPec ? 3 : 7,
message:
!isPec &&
t('components.BillingInfoForm.sdiMessageError'),
},
validate: {
value: (value) => {
if (isPec && sdiOrPec.pecEmail) {
return (
isEmailValid(sdiOrPec.pecEmail) ||
t('components.SignupForm.emailError')
)
}
},
},
})}
/>
{errors[isPec ? 'pecEmail' : 'sdiCode'] && (
<small>
{errors[isPec ? 'pecEmail' : 'sdiCode'].message}
</small>
)}
</div>
</div>
Thanks

Can I change the order of li elements conditionally in React

I have a list with side menu options, some of them are normal categories, some of them are static, here is my code:
//const type = the type is either categories or static
{items.map((item, index) => {
return (
<li>
{type !== 'categories' ? (
<> Static </>
) : (
<> Category </>
)}
</li>
);
})}
So in the items that are of type static I have a variable that comes from the back end which is called display, its value could be either 'top' or 'bottom', what I want to do is, if the type is equal to 'static', to move the order of the li to the value item.display has, for example:
<li>----</li> //type static //item.display: top
<li>++++</li> //type static //item.display: bottom
<li>""""</li> //type categories //item.display doesn't exist here
<li>::::</li> //type categories //item.display doesn't exist here
In the example above the li filled with the symbol '+' has a value of display: bottom,
so it should go to the bottom of the list and the list should now look like that:
<li>----</li> //type static //item.display: top
<li>""""</li> //type categories //item.display doesn't exist here
<li>::::</li> //type categories //item.display doesn't exist here
<li>++++</li> //type static //item.display: bottom
How can I implement that logic, I already tried doing it with inline styles like so:
<li style={{order: item.display === "top" ? items.length.toString() : "1"}}>
I am not even sure if this is a viable HTML, but it didn't work anyway, what are your suggestions for solving this problem?
You can control the order using items.sort() before you map it into virtual dom nodes.
Example:
import React from 'react'
function App() {
let items = [
{ text: '----', type: 'static', display: 'top' },
{ text: '++++', type: 'static', display: 'bottom' },
{ text: '""""', type: 'categories' },
{ text: '::::', type: 'categories' },
]
return (
<ul>
{items
.sort((a, b) =>
a.display === b.display
? 0
: a.display === 'top'
? -1
: a.display === 'bottom'
? 1
: 0,
)
.map(item => (
<li>
{item.type !== 'categories' ? (
<> Static </>
) : (
<> Category </>
)}
</li>
))}
</ul>
)
}
export default App
output:
<ul>
<li>----</li>
<li>""""</li>
<li>::::</li>
<li>++++</li>
</ul>
A possible solution would be that you have a mapping from string to number and a little helper function
const displayMap = {
top: 0,
default: 1,
bottom: 2
};
const compareDisplay(a,b){
let disp1 = a.display ?? 'default';
let disp2 = b.display ?? 'default';
return displayMap[disp1] > displayMap[disp2] ? 1 : -1;
}
in case if display is not defined, it will take default, which is mapped to the middle value
In case display also contains other values than top or bottom, you need to add a bit of logic to the helper function
you can use this mapping, to sort your objects before mapping
{
items.sort((a,b) => compareDisplay(a,b)).map((item, index) => {
return (
<li>
{
type !== 'categories' ?
(<> Static </>) :
(<> Category </>)
}
</li>
);
})}

Categories

Resources