Set HTML as default value of undefined variable in Angular JS - angularjs

I have a variable that could be potentially unset like this
{{salesperson || 'not set'}}
I want to add a CSS class to the not set area like this
{{salesperson || '<span class="error">- Not Set -</span>'}}
When I tried that it throws syntax errors.

HTML in expressions is escaped by angular, to avoid HTML/JS injections.
Use ng-class:
<span ng-class="{error: !salesperson}">{{salesperson || 'not set'}}</span>
Or simply ng-show/ng-hide:
<span ng-hide="salesperson" class="error">not set</span>
<span ng-show="salesperson">{{ salesperson }}</span>

So if you really, really want to inject HTML, look at this question: With ng-bind-html-unsafe removed, how do I inject HTML?
But if you just want to show an error if it's not defined:
{{salesperson}}<span ng-if="!salesperson" class="error ng-cloak">- Not Set -</span>'
It will only show the span if salesperson is undefined. Make sure to define your ng-cloak css as well to prevent any flickering.

Related

ng-bind-html with angular-translate renders text instead of HTML tag

I'm back on an old AngularJS project (1.7.2) with angular-translate and I'm struggling with ng-bind-html.
In my HTML I wrote this
<span ng-bind-html="'LEFT_PANEL.VISITED_AFTER' | translate"></span>
The result I'm expecting is
<span>Visited <strong>after</strong> this date. </span>
What I have in my translation file is:
"VISITED_AFTER": "Visited <strong>after</strong> this date"
What I actually get is:
<span ng-bind-html="'LEFT_PANEL.VISITED_BEFORE' | translate" class="ng-binding ng-scope">
Visited <strong>before</strong> this date
</span>
What am I doing wrong ?
(yes I have ngSanitize in my modules)
Thanks
NgTranslate is using it's own Sanitizer (Docs)
To change the sanitize strategy globally use $translateProvider.useSanitizeValueStrategy("STRATEGY");
If you only want to have a different strategy for this element use the attribute translate-sanitize-strategy
Possible duplicate of this.
Seems to have to do with HTML decoding.
Add this function:
function decodeHtml(html) {
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
And surround what you're printing with: decodeHtml(...)
Actually just look at this plunkr

Conditional Expressions in Angular's View: What if a model is missing?

Supposed I've in controllers scope
$scope.user = {"username": "someUserName"};
and as you can see above there is no company information in it.
I want to show alternativ text in the view, if it is missing, like (Pseudo-Code):
{{ if "user.company" does not exist show "not set" may be with a certain style }}
Is there an Angular way to manage it elegantly?
Something like that would be great:
{{ user.company || 'Not set!'.class('danger') }}
In this case above I can find }} and replace it with || 'Not set!'.class('danger') }}
I am looking for a generic solution something like: "Show always a certain text with a certain style, if the corresponding model is missing" ?
Imagine you have to correct these values in 100 different views with different model values. What could you do?
You can use ng-if/ng-show/ng-hide
Like this
<div ng-if="!user.company">
Not set
</div>
I think it's more elegant do handle it with an expression.
Company: <div>{{user.company || 'Not Set'}}</div>
ng-if / ng-show / ng-hide should be used.
<div ng-if='!user.company'>Company not set</div>
<div ng-if='user.company'>{{user.company}}</div>
or
<div ng-hide='user.company'>Company not set</div>
<div ng-show='user.company'>{{user.company}}</div>
Note:
However if you pretend to change styles if a particular info exists/doesn't exist you can use ng-class. Example:
<div ng-class='{"no-company": !user.company}'>Company not set</div>
Than in css apply your styles:
.no-company {
background-color: red;
}
Bottom line:
If you want to show text, then use ng-if or ng-show/ng-hide.
If you want to change styles or apply effects using classes use ng-class.
Or you can mix the angular directives to achieve more complex results.

ng-class doesnot get evaluated

<div ng-if="question.type =='options'" ng-repeat="option in question.options" >
<ion-radio name="{{$parent.question.id}}"
ng-model="$parent.question.answer"
required ng-value="option.id"
ng-class="{'has-custom-error':submitted && questionForm.{{$parent.question.id}}.$invalid,
'has-custom-success':questionForm.{{$parent.question.id}}.$valid }"
>
{{option.text}}
</ion-radio>
</div>
I have to add has-custom-error on user submitting the form without selecting the option.That is form is not valid but the ng-classis not getting evaluated.
The demo code is over here:http://plnkr.co/edit/FwjoCTYONvi3BoFHNKFK?p=preview
I don't think it is possible to use {{ }} expressions on a ng-class expression. You should be able to use it like this questionForm[$parent.question.id]
Also I never got ng-class working with classes with - between the parts, only CamelCase like hasCustomError. So {hasCustomError: questionForm.$invalid} should work.
Have you considered using the styleClass ng-invalid-required that is already used by angular for your styling? It is usually a lot cleaner, since there is no need for all the ng-class expressions
There is at least one problem with your code. You must not use interpolation {{}} within your ng-class attribute. Here is the correct syntax:
ng-class="{'has-custom-error':submitted && questionForm[$parent.question.id].$invalid, 'has-custom-success':questionForm[$parent.question.id].$valid }"
When you are inside an Angular expression, you don't need the mustache braces. So your code should be:
<div ng-if="question.type =='options'" ng-repeat="option in question.options">
<ion-radio name="{{$parent.question.id}}"
ng-model="$parent.question.answer"
required ng-value="option.id"
ng-class="{'has-custom-error':submitted && questionForm[$parent.question.id].$invalid,
'has-custom-success':questionForm[$parent.question.id].$valid }">
{{option.text}}
</ion-radio>
</div>
The variable form a.b has been replaced by the indexer form a["b"] so that it is evaluated correctly.
You can't use double-mustached expressions ({{ ... }}) inside expressions. The ng-class value is already an expression of type object, so you're supposed to use JavaScript syntax inside this attribute:
ng-class="{'has-custom-error': submitted && questionForm[$parent.question.id].$invalid,
'has-custom-success': questionForm[$parent.question.id].$valid }"
The use of $parent is also unecessary. BTW, you're not using it for your ng-repeat expression:
ng-repeat="option in question.options"
So you should simply use question instead of $parent.question: the scope of the ng-repeat block inherits from its parent scope, and the question is thus available through inheritance.
Note that, playing with your plunkr, it seems like the ion-radio directive that you're using doesn't correctly set the name attribute of the input it generates. This is probably why the CSS classes don't appear.
ng-form is the solution to my problem.But the problem that I am facing is in the name attribute of my ion-radio directive. For radio hence i used angular ng-invalid-required.And for other html tag i used ng-form.$invalid

AngularJS ng-class not applying css styles

I have a company site that I am developing with AngularJS and I am having some troubles with ng-class
Here is my HTML:
<a href="timeEntry.php" ng-class="{{(userRole.admin) ? '' : 'inactive'}}">
LINK
</a>
CSS:
.inactive {
pointer-events : none;
cursor : default;
}
Chrome Inspect Element:
<a href="timeEntry.php" ng-class="inactive">
LINK
</a>
Obviously I have tested class="inactive" and it is working as it should, Chrome's view source appears to be showing me something that should be working but it is not being applied.
Assuming userRole.admin is a boolean, this should work
<a href="timeEntry.php" ng-class="{ inactive: !userRole.admin }">
LINK
</a>
I think this will work:
Link
you can also have multiple conditions in the object, just put commas between them. The format is cssClass:<boolean expression>
ng-class expects an expression, so in your original code the part inside {{}} is being evaluated, and then angular is again evaluating the result of that, trying to interpret 'inactive' as a variable name. If you want to use a ternary just omit the {{}} from your original code
<a href="timeEntry.php" ng-class="userRole.admin ? '' : 'inactive'">
LINK
But for this particular example, the solutions provided by others using the object format are preferred.

Possible bug using using ng-switch with Select tag in AngularJS

The Select tag I am using in conjunction with ng-switch does not properly display nor function properly after being set once.
<select ng-model="visuals" ng-options="visual for visual in visuals">
See JSFiddle:
http://jsfiddle.net/timothybone/UaFuc/3/
Thanks in advance!
:D
You should not bind visuals using ng-model as it is the list of items. Setting it replace the list value by the chosen item (which is a list of characters). Causing the strange behaviour.
<select ng-model="item" ng-options="visual for visual in visuals">
This new variable must be declared in the scope. It is also used to set an initial value:
$scope.item = 'none';
Your switch usage was also wrong, you need en enclose condition in the switching block.
<div ng-switch on="item">
<span ng-switch-when="lots">Youtube</span>
<span ng-switch-default></span>
</div>
If you want to set the content of the HTML using ng-bind-html-unsafe you should provide a variable as parameter (not sure how you could inject javascript that way).
<span ng-switch-when="lots" ng-bind-html-unsafe="youtube">Could not evaluate 'youtube' variable</span>
The span content is then replaced. Of course a new variable must be defined in the scope to hold the HTML content:
$scope.youtube = "<hr/>This is an HTML content<hr/>";
I updated the jsFiddle: http://jsfiddle.net/PMpLa/4/

Resources