I'm trying to conditionally apply a class to my component using an expression like this:
.map(function(list, index) {
<div className={"myClass " + (position === index ? 'active' : null)}>
}
But it keeps adding null as class, with an end result like this:
<div class="myClass active">...
<div class="myClass null">...
This is a simple example, with only 2 class names, so I could just replace null with the default class name. But in a more complex layout, I would need to duplicate the same name over and over again.
Is there a better approach to solve this problem?
You could use an empty string '' instead of null like:
.map(function(list, index) {
<div className={"myClass " + (position === index ? 'active' : '')}>
}
Also map should return a value:
.map(function(list, index) {
return <div className={"myClass " + (position === index ? 'active' : '')}>;
}
If you have multiple classes, you might consider building the list of classes from an array:
var classes = ["myClass"];
if (position === index) {
classes.push('active');
}
return (
<div className={classes.join(' ')}>
...
</div>
);
You can also consider using a helper function that will generate the className string from an object like this:
var classes = {
myClass: true,
active: position === index
};
classnames is one such utility (not the only one).
Remove the space from "myClass " to "myClass", then replace null with an empty string ""
.map(function(list, index) {
<div className={"myClass" + (position === index ? 'active' : "")}>
}
just use https://www.npmjs.com/package/classnames:
usage example:
<div className={cn({"active": position === index })} ></div>
Use && short-circuiting: className={"myClass " + (position === index && 'active')}
In this way, if position === index is false, because we are using &&, we short-circuit. JS skips over 'active' and we just move on with our lives.
React Solution:
className={`myClass ${index ? "active" : ""}`}
Different syntax
className={`myClass ${index && "active"}`}
Related
I'm fetching data from an API which, depending on the item clicked on my webpage, may or may not have JSON data in the 'description' key. I'm trying to set up a ternary operator so that if there is data present in 'description' it should display that data, and if not it should display 'No description'. This is all working fine when there is data in description (condition is true), but if there isn't (condition is false) the page breaks.
Is there any reason why this ternary operator isn't working?
<div id="popup">
<h2>{selectedEvent.name}</h2>
{selectedEvent.descriptions[0].description ? (
<p>{selectedEvent.descriptions[0].description}</p>
) : <p>No description</p>
}
</div>
Thanks
Always check for keys inside objects
const description = electedEvent.descriptions[0];
return (
<div id="popup">
<h2>{selectedEvent.name}</h2>
{description && description.description ? (
<p>{description.description}</p>
) : <p>No description</p>
}
</div>
)
Check this example above:
function getFee(isLoyalMember) {
return (isLoyalMember ? '$2.00' : '$10.00'); // here the first output gets
//returned if member is not
//loyal. If customer is loyal, we
//return $10.00 instead.
}
Let us console log that and see the output:
console.log(getFee(true));
// expected output: "$2.00"
console.log(getFee(false));
// expected output: "$10.00"
console.log(getFee(1));
// expected output: "$2.00"
To make yours work. Do the following:
const description = electedEvent.descriptions[0];
return (
<div id="popup">
<h2>{selectedEvent.name}</h2>
{description && description.description ? (
<p>{description.description}</p>
) : <p>No description</p>
}
</div>
)
I need help to solve this
let someVar
render(
{
this.props.someData.map((items) =>
items.someotherData.map((item) =>
(item.data1 > 5 && item.data2 == "more") ? classNames({ "classname1": true })
: (item.data1 > 5 && item.data2 == "less") ? classNames({ "classname2": true })
: classNames({ "classname3": true })
))
}
<div className = { someVar } ></div>
)
I need my output of if loop to be pass to the variable
I tried many method. Nothing worked. Please give the solution
render() {
let someVar
this.props.someData.forEach(items =>
items.someotherData.forEach(item =>
item.data1 > 5 && item.data2 == 'more'
? someVar = 'classname1'
: item.data1 > 5 && item.data2 == 'less'
? someVar = 'classname2'
: someVar = 'classname3'
)
)
return <div className={someVar}></div>
}
I didn't really get what you were trying to do. Are you calling some function with the class names or something? Here is my best try to solve your problem though.
First we create the variable,
Then we do data processing. You shouldn't use map but instead the forEach if you are not returning anything. You are also overwriting the variable for each item (is this preferred behaviour?).
Then we actually return the React part of the code. Render function always needs to return JSX or null. Inside JSX we can use the someVar in the className. The final value of className needs to be a string. That's why we are putting strings to the someVar.
This is a JSX gist I'm displaying on the page.
rows.push(
<tr key={i}>
<td>{this.state['Person Name'] && this.state['Person Name'][i]}</td>
<td>{this.state['Amount'] && this.state['Amount'][i]}</td>
{this.state['Memo'] && this.state['Memo'].length > 0 ? <td>{this.state['Memo'][i]}</td> : undefined}
{this.state['Comment'] && this.state['Comment'].length > 0 ? <td>{this.state['Comment'][i]}</td> : undefined}
{this.state['Incurred Date'] && this.state['Incurred Date'].length > 0 ? <td>{this.state['Incurred Date'][i]}</td> : undefined}
{this.state['Entry Date'] && this.state['Entry Date'].length > 0 ? <td>{this.state['Entry Date'][i]}</td> : undefined}
<td>{this.state['Billable'] && this.state['Billable'][i]}</td>
<td>{this.state.fileName === 'expenses.csv' ? 'Expense' : 'Time'}</td>
</tr>
)
Somehow the conditions that are falsy still display empty <td>s to the table. What did I miss?
Empty columns are shown above.
You don't need to use ternary operators at all. Simply just chain &&'s.
{this.state.Memo && this.state.Memo[i] && <td>{this.state.Memo[i]}</td>}
{this.state.Comment && this.state.Comment[i] && <td>{this.state.Comment[i]}</td>}
{this.state['Incurred Date'] && this.state['Incurred Date'][i] && <td>{this.state['Incurred Date'][i]}</td>}
{this.state['Entry Date'] && this.state['Entry Date'][i] && <td>{this.state['Entry Date'][i]}</td>}
In addition, your array seems to be badly formatted:
// 2 separate variables for the same data?
this.memo = ['a', 'b'];
this.comment = ['comment', 'comment2'];
// Why not make it an array like this?
this.rows = [
{
Memo: 'a',
Comment: 'comment'
},
{
Memo: 'b',
Comment: 'comment2'
}
];
Then you can simply do:
this.rows.map(row => (
<tr key={row.id}>
<td>{row['Person Name']}</td>
<td>{row['Amount']}</td>
{this.state.hasMemos && <td>{row.Memo}</td>}
...
</tr>
)}
A <td> shouldn't be conditional on a row level, it should be conditional on a table level. You can't simply skip TD's if there isn't data for that row, as it will throw off the whole row by shifting columns over. You should either display N/A, an empty <td></td> for rows that may not have data, or hide them entirely on a table level via something like this.state.hasMemos, if there are any memos.
If you're using the new array structure I have listed, you can use this function to determine if any row has a memo:
this.array.some(row => row.Memo);
This will return true if any row has a Memo, thus either hiding the <td> for the entire table, or displaying it for every row.
I'm looking how to make a repeat item carousel which has if just key 0 that have class action if I using it in return it's error and if I using variable in return pug .carousel-item${activeornot}
return _.map(this.props.editor_pick_data, function (value, key){
if(key == 0){
}
return (
pug`
.carousel-item.active(key=${key}, style=${{display: 'relative'}})
.col-md-3.col-sm-6.col-xs-12npm
a.thumbnail(href="#")
img.img-responsive(src=${value.item.images[1].big_thumbnail})
`
)
})
It looks like you're just trying to add active class if key === 0. I think you can have a className variable as well:
className=${key == 0 ? 'active' : ''}
-
renderCarouselItem() {
return _.map(this.props.editor_pick_data, function(value, key) {
return (
pug`
.carousel-item(key=${key}, style=${{display: 'relative'}}, className=${key == 0 ? 'active' : ''})
.col-md-3.col-sm-6.col-xs-12npm
a.thumbnail(href="#")
img.img-responsive(src=${value.item.images[1].big_thumbnail})
`
);
})
}
Maybe you can do something like this:
className={`carousel-item ${key == 0 ? 'active' : ''}`}
this work but i dont know this is the best practice
renderCarouselItem() {
return _.map(this.props.editor_pick_data, function (value, key){
let html = [];
if(key == 0){
html.push(pug`
.carousel-item.active(key=${key}, style=${{display: 'relative'}})
.col-md-3.col-sm-6.col-xs-12npm
a.thumbnail(href="#")
img.img-responsive(src=${value.item.images[1].big_thumbnail})
`)
}else{
html.push(pug`
.carousel-item(key=${key}, style=${{display: 'relative'}})
.col-md-3.col-sm-6.col-xs-12npm
a.thumbnail(href="#")
img.img-responsive(src=${value.item.images[1].big_thumbnail})
`)
}
return (
pug`
${html[0]}
`
)
})
}
I have a div as following:
<div className={classNames("div-one",
{"half-width": this.state.showRegistration || this.state.showLogin})}>
</div>
What I want is: on !this.state.showRegistration || !this.state.showLogin this condition I want append "full-width" class to div-one instead of "half-width"
How can I achieve this?
!this.state.showRegistration || !this.state.showLogin
is not the negation of
this.state.showRegistration || this.state.showLogin
The proper negation would be !this.state.showRegistration && !this.state.showLogin.
But I guess you want something like this:
const registrationOrLogin = this.state.showRegistration || this.state.showLogin;
const classes = classNames("div-one", {
"half-width": registrationOrLogin,
"full-width": !registrationOrLogin
})
<div className={classes}}>
</div>
or
const classes = `div-one ${registrationOrLogin ? "half-width" : "full-width"}`;
const resultClass = {this.state.showRegistration || this.state.showLogin ? 'half-width' : 'full-width'};
<div className={classNames("div-one",
[resultClass]: true }>
</div>