How to conditionally add/remove classes with TailwindCSS and React - reactjs

I have an expression that looks for form errors and appends a div if once bubbles up:
{touched && normalizedError && (
<div className="visible alert-error text-xs text-red-500" role="alert">
{normalizedError}
</div>
)}
I'd like to refactor this and always display the div beneath my input elements but use the invisble class to hide them from the user unless an error is returned—in which case I'd conditional add the visible class.
What's the best way to accomplish this?

There are several ways to accomplish what you want, the easiest would be to add the conditional in the className itself
<div className={`alert-error text-xs text-red-500 ${touched && normalizedError ? 'visible' : 'invisible'}`} role="alert">
{normalizedError}
</div>

There are many different ways of getting this done.
1.Inline inside the class
<div className={`... ${touched && normalizedError ? 'visible' : 'invisible'}`}>
{normalizedError}
</div>
2. Using a variable
let dependentClass = touched && normalizedError ? 'visible' : 'invisible';
className={`... ${dependentClass }`}
3. Using clsx
<div className={clsx('...',`${touched && normalizedError ? 'visible' : 'invisible'}`)}>
{normalizedError}
</div>

Related

Conditionally apply CSS classes in React

I know this has been answered but I couldn't figure out what is wrong with my code here. I'm trying to add a class based of the conditional field.
React Code:
<div className="boards {task.IsClosed !== 0 ? 'complete' : ''}">
<p>{task.TaskName}</p>
<div>{task.IsClosed !== 0 ? <div>Completed</div> : null}</div>
</div>
Output:
<div class="boards {task.IsClosed !== 0 ? 'complete' : ''}">
<p>Task 2</p>
<div><div>Completed</div></div>
</div>
I want the output to be <div class="boards complete">
<div className=`boards ${task.IsClosed !== 0 ? 'complete' : ''}`>
<p>{task.TaskName}</p>
<div>{task.IsClosed !== 0 ? <div>Completed</div> : null}</div>
</div>
I think you want this^^^
for string interpolation in javascript the ` character must be used for quotes and the expression being interpolated must be within ${}
...
or you can make a variable to store the class i.e.
let className = task.IsClosed !== 0 ? 'complete' : '';
...
...
<div className={className}>
<p>{task.TaskName}</p>
<div>{task.IsClosed !== 0 ? <div>Completed</div> : null}</div>
</div>

One output from one array and different output from an array which is nested inside

I have two arrays configuration and sensordata, I want div elements to get displayed when there is a match otherwise another div elements.
//configuration is the first loop
this.props.configuration.forEach((wheel, index) => {
// sensor data is the nested loop
this.props.sensorData.forEach((sensor) => {
if (wheel.wheel) {
//Here I am checking if wheel doesn't exists in sensor
if(wheel.wheel!=sensor.sub_item)
axles.push( //divs to get displayed
<div className='twoaxlewheels' id={axleIndex}>
<span className='infotype' id={wheel.wheel}>9 Bar 16 Pressure</span>
<span className='TyreImage' id={wheel.wheel}><img src={tyre5} /> </span>
</div>)
//If wheel exist in sensor
if (sensor.sub_item == wheel.wheel) {
axles.push( //divs to get displayed
<div className='twoaxlewheels' id={axleIndex}>
<span className='infotype' id={wheel.wheel}>{wheel.wheel == sensor.sub_item ? sensor.temp : ''}</span>
<span className='TyreImage' id={wheel.wheel}>{wheel.wheel == sensor.sub_item ? <img src={tyre5} /> : ''} </span>
</div>)
}
}
})
return axles //returning axles here
})
With above code I am looping multiple times. I couldn't loop it properly.
If I did understand well, your issue is with the conditional rendering ? To display JSX when a condition is true ?
(https://reactjs.org/docs/conditional-rendering.html)
If that's the case, you can do in the return of your function, like :
return (<>
{this.props.sensorData.forEach((sensor) => {
wheel.wheel != sensor.sub_item ? (<div className='twoaxlewheels' id={axleIndex}>
<span className='infotype' id={wheel.wheel}>9 Bar 16 Pressure</span>
<span className='TyreImage' id={wheel.wheel}><img src={tyre5} /> </span>
</div>) : ( <div className='twoaxlewheels' id={axleIndex}>
<span className='infotype' id={wheel.wheel}>{wheel.wheel == sensor.sub_item ? sensor.temp : ''}</span>
<span className='TyreImage' id={wheel.wheel}>{wheel.wheel == sensor.sub_item ? <img src={tyre5} /> : ''} </span>
</div>)</>}

Custom GroupRow rendering (mbrn/MaterialTable) React

I am customizing groupRow of mbrn/material-table, But I don't find any documents for doing it.
https://material-table.com/#/docs/features/grouping
So far I managed to make the groupRow and its working fine. But now I don't know how to render the table row on expanding the groupRow.
I tried using MTableBody but the records are not showing up
<tr className="MuiTableRow-root">
<td
className="MuiTableCell-root MuiTableCell-alignLeft MuiTableCell-paddingNone MuiTableCell-body py-2"
colSpan={visiblecolumns + isGroupedAndHidden}
>
<button className="d-flex Card w-100">
<div className="ml-3 text-left">
<div className="text--bold text--muted text--xs">
{props.groups[0].title}
</div>
<div className="pt-1 pb-1">
{groupheader.title == 'Priority' ? (
<Priority value={groupData.value} />
) : groupheader.title == 'Time' ? (
<DateFormatter value={groupData.value} relative={true} />
) : (
groupData.value
)}
</div>
</div>
<div className="ListGroupHeader__meta d-flex align-items-center justify-content-end">
<span className="ListGroupHeader__count ml-3 mr-1">
{alerts.length}
</span>{' '}
alert{alerts.length > 1 ? 's' : ''}
<ChevronRight
className="text-muted"
style={{ fontSize: '30px' }}
/>
</div>
</button>
<MTableBody {...props} />
</td>
</tr>
This is how my code looks like. Am so confused I don't know what am missing to make it work
CodeSandBox: https://codesandbox.io/s/festive-bell-5d76e
Provided by your reference, the documentation say
You can override grouped row component with overriding components.GroupRow
That's exactly what you did, you overrated the entire component, but that component had a lot of functionality that you've missed like the Expanding and showing the content of the group.
This is the original component - https://github.com/mbrn/material-table/blob/master/src/components/m-table-group-row.js
So what you had do is copy and change or create your own component with the same functionality.
In the next example, I took the original component and changed it according to your structure (this is far from perfect, just showing you the way).
I copied MTableGroupRow and MTableCell (because Cell component is part of TableRow and had to change) and called them CustomGroupRow and CustomCell.
https://codesandbox.io/s/frosty-forest-su2dl

How to Use amp-state in JSX?

I'm working on creating Google amp-page in a React project, and need to fetch JSON after a click.
A/C to amp.dev, i can use amp-state to fetch remote data
as
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku" />
How can i do the same in JSX, as writing [src] in such format leads to error
Any suggestion will be helpful.
Thanks in advance
You can replace [src] with data-amp-bind-src. The latter syntax has been introduced for JSX syntax compatibility.
I don't know this is the right way, but I think, this can be a turn around
If there is a better way, or if this is not recommended in any way, please comment
I needed to toggle visibility of option based on the selected option
<amp-selector
layout="container"
class="radio-selector"
on="select: AMP.setState({
selectedOption: event.targetOption,
})">
<div option="a_show">Option A</div>
<div option="b_show">Option B</div>
<div option="c_show">Option C</div>
</amp-selector>
<div className="options"
dangerouslySetInnerHTML={{
__html: `
<p [class]="selectedOption == 'a_show' ? 'show' : 'hide'" class="show">a</p>
<p [class]="selectedOption == 'b_show' ? 'show' : 'hide'" class="hide">b</p>
<p [class]="selectedOption == 'c_show' ? 'show' : 'hide'" class="hide">c</p>
`
}}
/>

Append (Concatenate) HTML Element To React props Value

I've a JSX like below. The below code is Working (Multiple Ternary Conditionals).
<div className="myClassName">
{this.props.addr? this.props.addr.phoneno : '' }
{this.props.addr? (<span
className='location'>
{this.props.addr.location}
</span>) : ''}
</div>
When I tried with below Syntax with a single Ternary Operator, I'm getting Error.
<div className="myClassName">
{this.props.addr? this.props.addr.phoneno (<span
className='location'>
{this.props.addr.location}
</span>) : '' }
</div>
All I wanted is to append a Span Element with phoneno value. How to do Proper Concatenation here in this Example??
React doesn't allow returning multiple child elements inside a block. So to solve this you can use React.Fragment. There's more explanation about Fragments here.
Below is the corrected syntax.
<div className="myClassName">
{this.props.addr ? (
<React.Fragment>
{this.props.addr.phoneno}
<span className='location'>
{this.props.addr.location}
</span>
</React.Fragment>) : '' }
</div>

Resources