AngularJS - HTML data binding UI issue - javascript

I am binding following in my HTML.
<div>{{user.address[0].addressline1}}, {{user.address[0].addressline2}}, {{user.address[0].city}}, {{user.address[0].state}}, {{user.address[0].zipcode}}</div>
The issue is if addressline1 is null, it unnecessarily shows the , at first.
And also some other fields can be null
So How to display comma only if the value is not null?

Or as a matter of style, you can use a turnery operator to check for the value then format it
{{ !!user.address[0].addressline1 ? user.address[0].addressline1 + ', ' : ''}}
This could be made as filter to be more intuitive
angular.module('myapp', []).filter('trailIfTrue', [function(){
return function(val, trail){
return !!val ? val + trail : '';
}
}]);
usage:
{{ user.address[0].addressline1 | trailIfTrue:',' }}
here is a plunker

User separate span and ng-show so the span will be shown only if user.address[0].addressline1 is not null
<span ng-show="user.address[0].addressline1">{{user.address[0].addressline1}},</span>
<span ng-show="user.address[0].addressline2">{{user.address[0]. addressline2}},</span>
<span ng-show="user.address[0].city">{{user.address[0].city}},</span>
//...
You can use any expression into ng-show Eg:
user.address[0].addressline1 != null
myObj.myIntAttr > 0 && < 10
myObj.myBoolAttr == false
//...

Related

Return multiple values from a function in Angular and use those values inside HTML div tag. The return values can't be assigned to variable in TS file

I have a function which returns a string, a css class and a boolean like this [false, green_box]. I want to utilise this values in below HTML but unfortunately I am unable to do so. How can I access the values? Since the function is called multiple times inside the HTML file I cannot assign the return values in a variable in typescript file.
Please note that I can use different function to return boolean value but the goal is to find a way to utilize multiple values returned from a function in HTML.
Below is my HTML
<div *ngIf="getClass('investing', 'plan')[0]"
class="prio_box dnd_move"
data-drag="list-1"
data-drag-index="0">
<span [ngClass]="getClass('investing', 'plan')[1]"
class="dnd_move clr-box">
</span>
<span class="drag_content dnd_move">Plan</span>
</div>
Here is my function,
getClass(component: string, value: any) {
component = component.toLowerCase();
value = value.replace(/\s/g, "");
let pathValue = this.control[component]
? this.control[component.toLowerCase()][value]
: null;
this.allGreen.add(pathValue);
return [pathValue == Status.Yes
? "green_box"
: pathValue == Status.DontKnow
? "yellow_box"
: "red_box",
pathValue == Status.Yes
? false
: pathValue == Status.DontKnow
? true
: true];
}
Try doing something like this:
<ng-container *ngIf="getClass('investing', 'plan') as class">
<div *ngIf="class[0]"
class="prio_box dnd_move"
data-drag="list-1"
data-drag-index="0">
<span class="dnd_move clr-box {{class[1] || ''}}">
</span>
<span class="drag_content dnd_move">Plan</span>
</div>
</ng-container>
Using this way, you can prevent function from being called multiple times.

Angular translate filter in ternary operator

I'm trying to translate my project into another language. I used angular translate library and provided an external JSON file with the translations. It looks like this:
{
"hello_world": "Hola Mundo"
}
When I'm using it with simple hardcoded strings it works just fine and I get my correct translations:
<p>{{ "hello_world" | translate }}</p>
But how to deal with the ternary operator in code like this?
<button> {{ conditionValue ? 'Show' : 'Hide' }} </button>
How to change those 'Show' and 'Hide' values into a translation filter with Angular Translate? I tried different ways but I got an invalid syntax errors.
Thanks!
I think if you wrap the ternary operator into (), it will work.
<button> {{ ( conditionValue ? 'Show' : 'Hide' ) | translate }} </button>
you may try for this:
here i make username online and offline when you choose soanish, the user online status will change into spnish based on ternary condition.
https://plnkr.co/edit/o16dpI?p=preview
[https://plnkr.co/edit/o16dpI?p=preview][1]
{{ ( userName ? 'Show' : 'Hide' ) | translate }}
I've just come up with the solution!
For ternary operators we have to use 'translate' directive instead of filter. And it works just fine:
{
"show_value": "Show",
"hide_value": "Hide",
}
<button translate> {{ conditionValue ? "show_value" : "hide_value" }} </button>
If exist prefix
{{ ('massmedias.' + (ctrl.actionType === 'add' ? 'add' : 'rename')) | translate }}
Here is your language JSON file
"CONFIGURATION": {
"NEW_TEMPLATE": "New Template",
"EDIT_TEMPLATE": "Edit Template"
}
CASE-I (With HTML tag)
<button> {{ ( variable === '5' ? 'CONFIGURATION.NEW_TEMPLATE' : 'CONFIGURATION.EDIT_TEMPLATE' ) | translate }} </button>
CASE-II (With some third party attribute)
<p-dialog header="{{(variable === '5' ? 'CONFIGURATION.NEW_TEMPLATE' : 'CONFIGURATION.EDIT_TEMPLATE') | translate}}">

JXS if else class doesn't work

{item.status}
<div className="{item.status !== '' ? 'hide' : ''} pull-right">Content</div>
Why above jsx has no effect? My item.status value is string. But in my DOM I can't see hide class been added.
This is because you have wrapped your ternary operator in " so it is treated as string. Try this instead:
{item.status}
<div class={"pull-right "+(item.status !== '' ? 'hide' : '')}>Content</div>
Beside what #rahul-pratap-singh said, consider using nice, tiny package called classnames - link here so you can use it like:
import classes from 'classnames';
// later on
<div className={classes({
"pull-right": true,
"hide": item.status !== '',
})} />
I think it leads to much cleaner code than joining string.
Or at least use es6 string interpolation - link here
// instead of
"pull-right "+(item.status !== '' ? 'hide' : '')
// with string interpolation
`pull-right ${item.status.length ? '' : 'hide'}`;

ng-class not working. Where did I do wrong?

I know there are many problems here listed like this. but I can't pinpoint where I did wrong..
<li ng-repeat="item in type.sub | orderBy:y" ng-click="openpic($parent.$index, $index)" ng-class="{ 'active': $parent.$index + ':' + $index == current }">
we have $scope.current variable, and a nested menu with numbering id like 1:2, 1:3, 1:4, 2:1, 2:2, 2:3 and so on.
Goal is very simple. I need to make this <li> active, if the $parent.$index:$index is equal to $scope.current. ID is set whenever openpic($parent.$index, $index) triggered. We have li.active class in css.
So, can someone please show me, what's missing in that code?
TRY 1:
Tried:
<li ng-repeat="item in type.sub | orderBy:y" ng-click="openpic($parent.$index, $index)" ng-class="{ 'active': $parent.$index + ':' + $index == $parent.current }">
Still not working.
TRY 2
I have something like this:
ng-class="{{ $parent.$index + ':' + $index == $parent.current && 'active' || '' }}"
and it shows as ng-class="active" but class attribute did not updated.
TRY 3
ng-class="{{ $parent.$index + ':' + $index == $parent.current && 'highlight' || '' }}"
it shows ng-class='highlight", but class still shows class="ng-binding ng-scope"
TRY 4
ng-class="isActive($parent.$index,$index)"
It solves the problem, but it seems a little bit overkill for a simple switch function. Any more ideas?
TRY 5
As per major-mann code suggestion that works at TRY 4, I made these adjustment, and surprisingly, it works.
ng-class="$parent.$index + ':' + $index == $parent.current && 'active' || ''"
That one works. Removed all braces completely ????
First of all make {{$parent.$index:$index}} to make sure to get the right data (I just never met such a method to data access) ;
If it's ok, then try use:
ng-class="$parent.$index:$index === current ? 'active' : ''"
Or (best way) use function for this:
ng-class="someFn($parent.$index)"
$scope.someFn = function(index){
//index, index:index, index[n] or something else;
return index === $scope.current ? 'active' : '';
};
Update:
If You want get access to parent ng-repeat, better use
<... ng-repeat="(index1, data1) in firstData">
<... ng-repeat="(index2, data2) in secondData">
<... ng-something="index1 operator index2 or function(index1, index2)">
I hope, it will help;
As pointed to in the comments, rather a non-answer, but usually it is best practice to try to keep code (even simple ternaries) inside the JavaScript blocks rather than inside the HTML. This generally makes debugging any issues you may be having infinitely easier to deal with.
So, for example, you could change your HTML to something like:
<li ng-repeat="..." ng-click="..." ng-class="isActive($parent.$index, $index)">
And in your controller, you could add something like:
$scope.menu= function isActive(pidx, idx) {
return {
active: pidx + ':' + idx === $scope.current
};
};
To achieve your desired result.
If you take this a step further, you will probably realize that it is even better to do something like
$scope.cls.menu = function(pidx, idx) {
return {
active: pidx + ':' + idx === $scope.current,
any: 'other',
dynamic: 'classes',
you: 'need'
};
}
And call the function appropriately in the view.

Else if in angular js template [duplicate]

This question already has answers here:
if else statement in AngularJS templates
(10 answers)
Closed 8 years ago.
I need to use else if in angularjs template .What is the syntax ?
For example in c i would write the code like below:
if (data.sender=='system')
{data.receiver}
else if (data.sender=='mail')
{data.receiver}
else {data.sender}
My code:
{{data.sender == 'System' ? data.receiver : ' '}}
{{data.sender =='mail' ? data.receiver : data.sender }}
{{(data.sender === 'system' || data.sender === 'mail') ? data.receiver : data.sender}}
There are no if-else syntax in angular templates as you are looking for. Too much logic in the templates makes it difficult to maintain. Here are two possible solutions:
<span ng-show="data.sender == 'mail' || data.sender=='system'">{{data.receiver}}</span>
<span ng-show="data.sender != 'mail' && data.sender!='system'">{{data.sender}}</span>
You can also use ng-switch in a similar way:
<span ng-switch="data.sender">
<span ng-switch-when="mail">{{data.receiver}}</span>
<span ng-switch-when="system">{{data.receiver}}</span>
<span ng-switch-default>{{data.sender}}</span>
</span>
The later having the advantage that only one of the spans will exist in the document where ng-show/ng-hide all spans exist in the document they are just hidden using display:none.
Other options would be writing your own directive, or creating special filters.
Here it is, but you should really try to avoid having this kind of complicated logic inside of templates, as a rule of thumb.
{{ data.sender == 'system' ? data.receiver : data.sender == 'mail' ? data.receiver : data.sender }}
If you need an elseif in angular template you can use a ternary operator as in C/C++
{{ data.sender=='system'
< 4 ? data.receiver : data.sender=='mail' ? data.receiver : data.sender}}
angular.module('quetion_app', []);
angular.module('quetion_app').controller('quertion_controller', ['$scope',
function($scope) {
$scope.data = {
sender: 'some sender',
receiver: 'somebody'
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="quetion_app">
<div ng-controller="quertion_controller">
{{data}}
<br>
<br>
{{ data.sender=='system'
< 4 ? data.receiver : data.sender=='mail' ? data.receiver : data.sender}} </div>
</div>
Change data.sender in snippet to check the behavior
Hope it helps
This type of logic really belongs in the controller or service which is responsible for setting up data in your $scope. Placing it in your view brings a lot of logic in to the view unnecessarily and also causes that logic to be run as a watch which both expensive and unnecessary.
In the code that establishes data you could have:
data.displayedSender = (data.sender === 'system' || data.sender === 'mail') ? data.receiver : data.sender;
Then in your view you bind to the data.displayed sender:
<span>{{data.displayedSender}}</span>

Categories

Resources