Combining text and JS in className after a ternary operator - javascript

I'm having trouble combining a text and CSS style after for className after a ternary/conditional. I've looked at so many different examples however nothing seems to be working.
<div className={key === active ? ({ 'column ' + styles.Active}) : ('column ')} key={key}>
Can anyone please show me how to best format this correctly? I need both the column and styles.Active classNames to appear if key === active.
Thank you in advance

this is the same solution, but the best approach
<div className={key === active ? `column ${styles.Active}` : 'column'}>
it's more readable, self explaining, and discreet, this is how you should write the code, not the otherway..
className expects a string and instead you gave it an object {'column ' + styles.Active} which is wrong.
also, i don't understand your logic. styles.Active would be an object which is of a style(style object). if that's the case you are doing it wrong again..
<div className="column" style={key === active ? styles.Active : {}}>

If you're ok with adding an npm package you can use classnames
import classNames from 'classnames';
...
<div className={classNames('column', { [styles.Active]: key === active })} key={key}>
=================
if you don't want to add an npm package
<div className={'column ' + (key === active ? styles.Active : '')} key={key}>

For readability it may be better to extract this into a variable. Though, the ternary could easily be inline.
String Literals
For those that prefer ES6+
// Ternary
const className = `column ${(key === active) ? styles.Active : ''}`;
// Or a little more readable
const className = 'column';
if (key === active) {
className += ` ${styles.Active}`;
}
...
<div className={className} key={key}>
Concatenation
It seems for the moment string concatenation is faster: (https://jsperf.com/es6-string-literals-vs-string-concatenation/49)
// Ternary
const className = 'column' + ((key === active) ? ' ' + styles.Active : '')}`;
// Or a little more readable
const className = 'column';
if (key === active) {
className += ' ' + styles.Active;
}
...
<div className={className} key={key}>

Try this one out. Take the column out , and have the ternary operated on just the key
<div className={'column ' + (key === active ? styles.Active : '')} key={key}>

I found an easy way to do it use an array and join it, it's bit old question but maybe it gonna help someone else.
className={ [ isMobile ? 'small' : 'large' , darkTheme ? 'dark' : 'light' , isSomething ? 'classX' : 'classY' ].join(' ') }

Related

React JSX - Ternary operator with multiple or conditions

I'm trying to render out a specific colour scheme for my footer based on the url pathname. The site only has 3 url's that require the colour scheme so I want to target them specifically. I'm wondering if there is a way to do it using the or/pipes operator or should I just put it in a switch statement?
var urlString = '/work' || '/wip' || '/journal';
<FooterContainer theme={ window.location.pathname == urlString ? 'dark' : 'light' }>
This is my simplified code so far, just wanted to test that dark or light is returned on the component. It works for the /work url but the rest of them it doesn't.
The condition '/work' || '/wip' || '/journal' will always return '/work' since it is considered a true value, so there is no need to check the other OR conditions. This is why it works for '/work' and nothing else.
I would like to recommend two approaches for this:
One is to write a straight forward function that returns true/false based on the pathname provided.
function checkUrl(pathname) {
if (pathname === '/work' || pathname === '/wip' || pathname === '/journal') {
return true;
}
return false;
}
<FooterContainer theme={ checkUrl(window.location.pathname) ? 'dark' : 'light' }>
Or a second approach to make an array with the dark theme compatible pathnames and check if the current window.location.pathname is in this array.
var darkThemePathnames = ['/work', '/wip', '/journal'];
<FooterContainer theme={ darkThemePathnames.includes(window.location.pathname) ? 'dark' : 'light' }>
If you would like to shorten it even more then you can just do:
<FooterContainer theme={ ['/work', '/wip', '/journal'].includes(window.location.pathname) ? 'dark' : 'light' }>

Angular - Ternary operator with a ternary operator response

I have a ternary operator in my angular HTML. I'm having difficulty with the formatting. If the value equals the files length, it should return Good, if it doesn't I need to check some custom values. I check to see if the custom value exists (customs?.album_title) and then determine what to show. If both options were strings, it works completely fine. However, I need My Text to prepend the customs.album_title value and I'm not entirely sure how to do that. As you can see in the example below (which is naturally incorrect), the result would be customs?.album_title as a string, opposed to My Text + whatever the customs.album_title value is.
Any help would be greatly appreciated.
{{ value == files.length ? 'Good' : customs?.album_title ? 'My Text customs.album_title' : 'String Two' }}
Maybe you mean like this (using ${var})
{{ value == files.length ? 'Good' : customs?.album_title ? `My Text ${customs.album_title}` : 'String Two' }}
I'm not sure but I think Template Literals are not yet supported by Angular on HTML templates.
So for now, you can try to solve it by string concatenation
{{ value == files.length ? 'Good' : customs?.album_title ? ('My Text ' + customs.album_title) : 'String Two' }}
You can try this:
{{ value == files.length ? 'Good' : (customs?.album_title ? (('My Text ') + customs.album_title) : 'String Two') }}

Conditional logic jsx react

I am trying to apply more than 1 condition to className in my jsx view. However it won't let me.
It only listens to the first condition.
className={usernameFocus ? "toggled" : "" || usernameValidated ? "validated" : ""}
I have tried several combinations:
className={usernameFocus ? "toggled" : "" + usernameValidated ? "validated" : ""}
How could I accomplish more than one conditional to add classNames to my element?
Your order of operations is mixed up. Put your separate conditions in parentheses. Also, you can short-circuit the class evaluation like this:
className={(usernameFocus && "toggled") + " " + (usernameValidated && "validated")}
If you feel extra fancy, you can also use a template string:
className={`${usernameFocus && "toggled"} ${usernameValidated && "validated"}`}
If you do this a lot (multiple booleans), have a look at the officially recommended classnames module by Jed Watson. Link.
With it, you can do it like this:
var usernameClasses = classNames({
'validated': usernameValidated,
'toggled': usernameFocus
});
className={usernameClasses};
I think you are missing a space between the class names for when both are applied, also brackets help with multiple nested conditional statements.
Try this:
className={(usernameFocus ? "toggled" : "") + " " + (usernameValidated ? "validated" : "")}

Reading multiple ternary operator conditions

I've come across the following code:
if (proto.hasOwnProperty(name)) {
!(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) : invariant(false) : undefined;
}
How do you read the ternary operator in line 2?
As one of the comments says, you should probably convert this to a traditional if-else tree for readability/sanity. However, it would read like this (I haven't written it out verbatim for brevity's sake, but you get the gist):
if (!conditionOne) {
if (conditionTwo) {
return invariant(false, 'ReactClass...', name);
}
else {
return invariant(false);
}
}
else {
return undefined;
}
I figured answering this by converting to the code to an if-else tree may help you understand it a little easier :)
Try to format an indent your code for better understanding.
if (proto.hasOwnProperty(name)) {
!(
specPolicy === SpecPolicy.DEFINE_MANY //1
||
specPolicy === SpecPolicy.DEFINE_MANY_MERGED //1
) ?
process.env.NODE_ENV !== 'production' ? //2
invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) :
invariant(false)//3
: undefined;//4
}
(1) If specPolicy is neither SpecPolicy.DEFINE_MANY nor SpecPolicy.DEFINE_MANY_MERGED, then check if process.env.NODE_ENV is not "production".
(2) If so then call invariant(false, 'Re...., else call (3)invariant(false).
If (1) is true return undefined (4).
There are two ternary operators. See if this way of formating it helps:
!(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ?
process.env.NODE_ENV !== 'production' ?
invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) :
invariant(false) :
undefined;
You could use proper indents. The most inner ternary is grouped together like
condition1 ? condition2 ? value1 : value2 : value3
is the same as
condition1 ? (condition2 ? value1 : value2) : value3
With your code;
!(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ?
process.env.NODE_ENV !== 'production' ?
invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) :
invariant(false) :
undefined;

javascript two "?" operators one by one

Help me please understand how this piece of code are working.
function getOpacity( elem ) {
var filter = elem.style.filter;
return filter ?
filter.indexOf("opacity=") >= 0 ?
(parseFloat(filter.match(/opacity=([^)]+)/)[1]) / 100) + "" :
"" :
elem.style.opacity;
}
I was try console.log(filter) and received empty string. I thing something interesting going on with two "?" operators. I know for what there is one "?". But i need help with two such operators.
It's just nested conditional (i.e. ?:) operators. This code is equivalent to:
if (filter) {
if (filter.indexOf("opacity=") >= 0) {
return (parseFloat(filter.match(/opacity=([^)]+)/)[1]) / 100) + "";
} else {
return "";
}
} else {
return elem.style.opacity;
}
The default precedence for
a ? b : c ? d : e
is
a ? b : (c ? d : e)
and not, for example
(a ? b : c) ? d : e
This makes it easy to use the ? ternary operator much like a series of if/then/else statements without superfluous parentheses, although you're welcome to add them if you think they improve readability.

Categories

Resources