Conditional logic jsx react - javascript

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" : "")}

Related

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') }}

Default beginning value of innerHTML of a div

In my app, I need to check if a div container is empty before appending certain text elements to it (the innerHTML is created and removed many times in my app, hence the need to check for emptiness). The div is created very simply as below in the beginning. Why doesn't checking for an empty string as below work? I am expecting the alert to show the text Nothing, but it does not.
let targetContainer = document.getElementById("container")
let containerText = targetContainer.innerHTML
alert("Text: " + containerText == "" ? "Nothing" : containerText)
#container {
background-color: #0f2e0c;
}
<div id="container"></div>
Your main issue is with operator precedence. Currently, you code is evaluating like so:
("Text: " + containerText) == "" ? "Nothing" : containerText
in your code + has higher operator precedence than ==, meaning that the concatenation occurs before the == occurs. You can force the evaluation of the equality and the ternary to occur before the addition concatenation occurs by wrapping it in parenthesis to group your ternary operation. Since grouping has the highest operator precedence it will occur before your concatenation occurs:
"Text: " + (containerText == "" ? "Nothing" : containerText)
let targetContainer = document.getElementById("container")
let containerText = targetContainer.innerHTML
alert("Text: " + (containerText == "" ? "Nothing" : containerText));
#container {
background-color: #0f2e0c;
}
<div id="container"></div>

Combining text and JS in className after a ternary operator

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(' ') }

React. What is the wrong with my ternar operator in className?

So, I have a simple tag span with classNames that trigger on a special condition, but for some reason my class in the DOM does not appear. I got just class word without anything like <span class>...</span>.
My span tag:
<span key={total} className={'total' + ' ' + total === 0 ? 'total--empty' : ' '}>
{total ? total : 0}
</span>
It is parsed like a ternary* : (statement) ? whenTrue : whenFalse;
// Which, translated to your code makes:
{ ('total' + ' ' + total === 0) ? 'total--empty' : ' '}
A string is truthy, thus 'total--empty'. What you need:
{ 'total' + ' ' + (total === 0 ? 'total--empty' : ' ')}
* Most people call it the ternary operator, but it is actually called the conditional operator. It's a ternary operator (an operator accepting three operands), and currently JavaScript's only ternary operator, but that could change.
You should probably know about concept of Operator precedence.
In your case, you are using '+' operator (precedence of 13) and comparison '===' operator (precedence of 10).
Therefore, the expression:
{'total' + ' ' + total === 0 ? 'total--empty' : ' '}
...will always return falsy value i.e. space.
Lets say total value is 0, so your expression executes as 'total'+' '+0 which becomes a string "total 0" NOT EQUAL TO 0.
What you need to do is Grouping of expression using '()' round brackets (precedence of 20).
i.e.
{'total' + ' ' + (total === 0 ? 'total--empty' : ' ')}
which has possible truthy/falsy outcome i.e. "total " or "total total--empty"
You can try this below. We can make it with the help of curly braces and parenthesis.
Curly braces { } are special syntax in JSX. It is used to evaluate a JavaScript expression during compilation. A JavaScript expression can be a variable, function, an object, or any code that resolves into a value.
Parenthesis ( ) can be used to return something.
Curly braces versus parenthesis in ReactJS
<span className={"total "+(total !== 0 ? "total_empty": null )} />
{total ? total : 0}
</span>

Conditionally add string to HTML with Angular expression

I have the following :
<div>{{animalType}}</div>
which evaluates to dog.
Can I conditionally add an sif animalTypeevaluates to anything other than dog?
Something like this : which doesn't work
<div>{{animalType}} {{'s' : !animalType == 'dog'}}</div>
So I would getcats
Use ternary operator in expression as follow:
<div>{{animalType}}{{animalType != 'dog' ? 's' : '' }}</div>
Alternatively
<div>{{animalType}}<span ng-show="animalType!='dog'">s</span></div>
Not tested, but try this simple snippet:
<div>{{animalType === "dog" ? animalType : "s"}}</div>
By the way, if you want to switch only between two values, from my point of view, logically appealing would be something like that:
<div>{{isDog ? "dog" : "s"}}</div>
$scope.isDog = true/false
You could also use ng-if
<div>{{animalType}}<div ng-if="animalType !== 'dog'">s</div></div>

Categories

Resources