Ternary operator for values in Angular 2+ template - html

I have in my template something like this:
<span *ngIf="selectedSport.key === 'walking'"> steps </span>
<span *ngIf="selectedSport.key !== 'walking'"> km </span>
I found this spelling quite ugly, and two lines for this... Meh. So I tried to look for alternatives to this.
NgIfElse
<span *ngIf="selectedSport.key === 'walking'; else elseSpan"> steps </span>
<ng-template #elseSpan> km </ng-template>
I found this one better, however it may be tricky to use in case of multi-condition like *ngIf="A && B". And we still have two code lines in template...
get function
<span> {{getUnit(selectedSport.key)}} </span>
getUnit(sportKey: string): string {
return sportKey === 'walking' ? 'steps' : 'km';
}
This is quite better as template gets more readable. However I would like not to add a function in my component for this.
Do you know if Angular 2+ templates support ternary operators as in the getUnit function?
Do you have any better idea?

You can use Conditional (ternary) operator, inside of template like below example
<span> {{selectedSport.key === 'walking' ? 'steps' : 'km'}} </span>

It seems that you are trying to display unit of selected sport.
It is better to keep the logic in controller and populate it in model
object and view just display the model.
Diluting the logic in
view layer may not a better design and violates law of single
responsibility.

if you want multiple ternary operator you can use like that
<span >{{this.commentsType === itemType.All ? counter.allCounts : this.commentsType === itemType.Project ? counter.projectCount : this.commentsType === itemType.Customer ? counter.customerCommunication : 0}}</span>

Related

How to insert HTML inside template literal strings?

In React, I want to be able to use style words within a string which is defined in a variable using template literals.
For that I am making use of a to just style that word.
I am getting HTMLIntrinsic usage error.
Note- Solutions given in SO to questions related to this does not solve the issue I have. Pls check the code.
How to circumvent this problem
Tried using dangerouslyinsertHTML, but not a recommended solution.
//Actual code
const temperature = "22";
const list = {
item: `The temperature is ${temperature}`
}
//To style it-
const temperature = "22";
const list = {
item: `The temperature is <span style={{color:'red'}}>${temperature}</span>`
}
//And the above list.item is inserted inside JSX like -
return (
<div>{list.item}</div>
)
The temperature(22) needs to be styled.
Instead of the template string, you can use JSX elements for generating HTML as usual, placed next to your text elements. Example:
item: (
<>
The temperature is
<span style={{color:'red'}}>
{temperature}
</span>
</>
)
I'm using a Fragment to wrap the text and elements together, but you can use something else like a div if you wish to style the wrapper too.
You can't use React in template-literal like that because the React component is an object. Using it with template-literal will result in this[object Object] . So I recommend use other way, for example the solution by #richardo
You can make this as simple as this, IF you are OK to not have object like you defined
return(
<div>The temperature is <span style={{color: 'red'}}>{temperature}</span></div>
)

Html.Raw() in combination with Razor?

I am trying to add a <span> to my view when my session variable is not null.
The value of Session["error"] has the right value (I checked), but there is no <span> coming in my view when it is filled while the code DOES come into the IF statement.
#if (Session["error"] != null) { Html.Raw("<span class=\"alert\"> #Session[\"error\"].ToString() <span>"); }
Plz tell me what i need to change. I am a student and new to coding.
You need to add # to write the output of the function to the response stream. In short; #Html.Raw().
However, this is not how Razor code should be used. Instead you can embed HTML directly within your if, like so:
#if (Session["error"] != null)
{
<span class="alert">#Session["error"]</span>
}

Tally Up Number of Occurrences in Angular

So basically I have this quiz app im working on using angular and I want to tally up the amount of times the right answer is entered. I already made it so the words 'CORRECT' are displayed by the question if they type the right answer in the text box, but I want to see how many times that happens. Here is my code
div ng-repeat="q in questions">
<span>{{ q.question }}</span><br>
<input type="text" ng-model="q.ans" name="email" placeholder="">
<div ng-show="q.ans===q.answer">CORRECT!</div>
<div>
so basically questions is just an array with a question string and answer string. I want to see at the end how many are correct. So I'm thinking, I added in a correct property to the question objects that has a default of 0 which could mean wrong, and change when its right to 1.
Now how would I make it change from the html page here when someone types the right answer? like if correct is shown, if the ng-show is right, then that value would be 1, if not, it'd be 0.
thanks for any assistance. Wondering if I could do this in real time instead of having a 'check' button at the end.
EDIT: okay I looking around the ng-if directive, would it somehow be possible to add like
<div ng-if="q.ans===q.answer">{{ q.correct = 1 }} </div>
or somehow execute that q.correct = 1 (meaning that answer is correct) if the ng-if block is run?
Make a filter for counting the correct answers
// app is your module
app.filter('correctCount', function() {
return function(questions) {
return questions.reduce(function(count, q) {
return count + (q.ans === q.answer ? 1 : 0);
}, 0);
};
})
Then you can display the total in your template
Total: {{questions | correctCount | number}}
Demo ~ http://plnkr.co/edit/br3fxHQ8q04ajZj6Fxch?p=preview
An alternative to reduce that might be easier to understand is...
return questions.filter(function(q) {
return q.ans === q.answer;
}).length;

stop ng-repeat when match ng-if

I have an object person like this:
person:
phone:
phone1:
number:"xxx-xxx-xxxx"
checkedSms:true/false
phone2:
number:"xxx-xxx-xxxx"
checkedSms:true/false
smsNumber:""
I have a link <a> I only want to display it under certain condition: either one of the phones checkedSms is true(person.phone.phone[i].checkedSms = true) or smsNumber.length > 0.
I can do the second part by this:
<a ng-click="..." ng-if="person.smsNumber.length > 0"
<div>
...
</div>
</a>
But I don't know how to add the first part, and combine it with the second part above. Tried ng-repeat to repeatly checking on phones of person, but multiple matching results in multiple <a> display. The link should only show once, whenever one condition matches, it should stop further checking.
Hope somebody can help me out. Thanks a lot.
This is how I would do it.
In the HTML:
<a ng-if="checkForSms()" ng-click="...">
In the controller:
$scope.checkForSms = function() {
// code that returns true if the conditions are met
}
Also, I would start using "controllerAs" syntax to prepare for Angular 2.0. https://www.airpair.com/angularjs/posts/preparing-for-the-future-of-angularjs#3-2-remove-dependencies-on-scope
I would create a property in the controller, call it filterPersonList
$scope.filterPersonList = $scope.personList.filter(function (e) {
return e.smsNumber.length > 0 || whatever other condition
})
Then use ng-repeat with the filterPersonList

nested ternary operator vs nested if else, which is better in readability purpose

I found code in code review which was written by my team member. It contains nested ternary operator. I told him to use if else if there is more than one nesting for readability purpose. We had argue on that.
following is code
ColorEnum color = opacity == Opacity.FIVE? ColorEnum.BLACK :
opacity == Opacity.TEN? ColorEnum.WHITE :
opacity == Opacity.FIFTY? ColorEnum.RED :
opacity == Opacity.TWENTY? ColorEnum.BLUE :
opacity == Opacity.FIFTEEN? ColorEnum.PURPLE : null;
And this code is changing as new configurations come.
So What is better here? ternary operator or if else?
Just reformatting your code makes it quite clear:
ColorEnum color =
opacity == Opacity.FIVE ? ColorEnum.BLACK
: opacity == Opacity.TEN ? ColorEnum.WHITE
: opacity == Opacity.FIFTY ? ColorEnum.RED
: opacity == Opacity.TWENTY ? ColorEnum.BLUE
: opacity == Opacity.FIFTEEN ? ColorEnum.PURPLE
: null;
LISP adopts the cond construct which has both the same structure and the same semantics, and is considered good practice. As an aside, Clojure also supports a form which tests the value of a single expression with a single predicate applied to different values (one for each clause) and calls it condp—that would be a perfect match for your use case.
The idiom with the ternary operator has the advantage over an if-else cascade for being an expression so you need only a single statement to assign it to the variable. if-else will force you to pull the assignment into each then clause, introducing more boilerplate and more opportunity to fail on correctness.
A switch statement could also be considered as an alternative, but it would have the following deficiencies:
like if-else, it is not an expression;
you are restricted to just different constant values of a single expression (the type of the expression being quite constrained, too).
it's prone to bugs due to the boilerplate break missing somewhere.
I would suggest to use switch statement. It would be more readable than ternary and if-else.
switch(opticity)
{
case Opticity.FIVE: color = ColorEnum.BLACK;
break;
case Opticity.TEN: color = ColorEnum.WHITE;
break;
case Opticity.FIFTY: color = ColorEnum.RED;
break;
....
default: printf("Error message\n");
}
For this purpose, probably a switch-case statement would be best in terms of readability.
Go with switch.
I've a thumb rule which I consistently follow (Although not hardset)
1) Only one conditional evaluation, go with ternary operator
2) Two conditional check, go with if(){} else if(){ } else{} construct
3) Three or more go with switch ladder
“Programs must be written for people to read, and only incidentally for machines to execute.”
― Harold Abelson, Structure and Interpretation of Computer Programs
As others have mentioned, a switch would be a good alternative. To reduce boilerplate code (breaks, assignments), I would further recommend putting the switch into a dedicated method:
(All examples are in C#)
public ColorEnum OpacityToColor(Opacity opacity)
{
switch (opacity)
{
case Opacity.FIVE:
return ColorEnum.BLACK;
case Opacity.TEN:
return ColorEnum.WHITE;
case Opacity.FIFTY:
return ColorEnum.RED;
case Opacity.TWENTY:
return ColorEnum.BLUE;
case Opacity.FIFTEEN:
return ColorEnum.PURPLE;
default:
throw new System.ArgumentOutOfRangeException("opacity");
}
}
// Elsewhere
ColorEnum color = OpacityToColor(opacity);
If your language has a neat dictionary/map initialization syntax (e.g. Python, C#), you could also use that for a very concise and clear notation:
public static readonly Dictionary<Opacity, ColorEnum> ColorByOpacity =
new Dictionary<Opacity, ColorEnum>
{
{Opacity.FIVE, ColorEnum.BLACK},
{Opacity.TEN, ColorEnum.WHITE},
{Opacity.FIFTY, ColorEnum.RED},
{Opacity.TWENTY, ColorEnum.BLUE},
{Opacity.FIFTEEN, ColorEnum.PURPLE}
};
// Elsewhere
ColorEnum color = ColorByOpacity[opacity];