I have this html code
<empty-list [hidden]="!emptylist" text="There is currently No User"</empty-list>
<div *ngFor="let userObser of userObservables">
<ion-item #emptylist *ngIf="userObser | async as user">
<h2>{{user.displayName}}</h2>
<h3>{{user.email}}</h3>
</ion-item>
</div>
I want to show the empty list if there is no user & hide it if there is at least one.
I know I can do it using a subscribe method,but I want to use async pipe also I need to unsubscribe each time I use a subscribe which is really not efficient.
My question is there a way I could create a local variable inside the ion-item the ntest test if it exists outside & therefore use it in the hidden input ? It's just a suggestion I can't really seem to make it work.
You can use a simple else inside the ngIf to display another template if the condition doesn't match:
<ng-container *ngIf="userObservables.length > 0; else emptyList">
<ng-container *ngFor="let user of userObservables">
<ion-item *ngIf="user | async as user">…</ion-item>
</ng-container>
</ng-container>
<ng-template #emptyList>
<empty-list>…</empty-list>
</ng-template>
Note that I also replaced your seemingly unnecessary div with a ng-container to avoid unnecessary DOM nodes.
As a side note to your own suggestion: template references cannot be accessed from outside the template boundary. Structural directives like *ngIf and *ngFor create their own template, so this becomes a boundary. That's why
<h2>{{ ref.innerText }}</h2>
<ng-container>
<span #ref>Hello, World</span>
</ng-container>
will work, but
<h2>{{ ref.innerText }}</h2>
<ng-container *ngIf="true">
<span #ref>Hello, World</span>
</ng-container>
won't work.
Related
I have a list of child components inside a ngFor:
<ng-container *ngFor="let field of fields">
<button (click)="show = !show">Show</button>
<ng-container *ngIf="show">
<app-field [fieldInfo]="field"></app-field>
</ng-container>
</ng-container>
I want to only show this specific app-field component if show is true, but this is obviously not the way, because it sets show to true for all of the rendered components.
My problem is really that I cant show all of the app-fields because they turn my app into a slow mess when they are displayed (there will be hundreds of them), so I only want to display them when they are needed.
How can I toggle the rendering of each specific component on/off uppon click? Or is there som other solution I could look into?
show variable is global and updating value for show will reflect for all the app-field components, Thus You need to determine and specify a show/hide variable for each component individually.
To do that you should add a show member inside the field Object as follow:
<ng-container *ngFor="let field of fields">
<button (click)="field.show = !field.show">Show</button>
<ng-container *ngIf="field.show">
<app-field [fieldInfo]="field"></app-field>
</ng-container>
</ng-container>
Also found similar solution, check this answer
I needed to only have the component be attached to the DOM when set to be visible. Solved it with the answer in: Thierry Templier answer here
Inside parent component:
public showField: any = {};
Then in parent component template:
<ng-container *ngFor="let field of fields">
<button (click)="showField[childField.id] = !showField[childField.id]">Show</button>
<ng-container *ngIf="showField[childField.id]">
<app-field [fieldInfo]="field"></app-field>
</ng-container>
</ng-container>
This destroys the component when *ngIf is false, which is what I needed in this situation.
Thanks to #yazan for leading me to the answer.
First of all, want to emphasize that I had already have a look at many pages e.g. Two switch case values in angular but they cannot fix my problem.
I have the following approach in the html page of my Angular project and I switch according to i parameter without any problem. On the other hand, there is a parameter called loading on component side and I also need to use this value in ngSwitchCase. But the following code does not work and ignore loading parameter's value. So, how can I use it?
<ng-container [ngSwitch]="i">
<ng-container *ngSwitchCase="i === 0 && loading === true">
<!-- other stuff -->
</ng-container>
</ng-container>
Create another ng-container inside with the loading condition.
<ng-container [ngSwitch]="i">
<ng-container *ngSwitchCase="0">
<ng-container *ngIf="loading">
// do stuff
</ng-container>
</ng-container>
</ng-container>
Im trying to assign a variable in my html in angular 4+. Is this possible?
What im trying to achieve is to assign a comparison to a variable, so i do not have to make always the same in all the cases i have.
Here is an example i want to achieve:
<mat-list-item role="list" *ngFor="let o of examles;" role="listitem">
<span *ngIf="o.type == 'EXAMPLE_TYPE'"> some text</span>
// here more divs
<span *ngIf="o.type == 'EXAMPLE_TYPE'"> other text</span>
// more divs...
<span *ngIf="o.type == 'EXAMPLE_TYPE'"> last text</span>
</mat-list-item>
So, my question is, is there any way to declare something like?
<div #isExampleType="o.type == 'EXAMPLE_TYPE'" >
And then use it in the *ngIf="isExampleType"...
This particular case is conveniently solved with component method:
<span *ngIf="isExampleType(o)"> some text</span>
Or a pipe:
<span *ngIf="o | exampleType"> some text</span>
Both will have nearly zero performance impact
There is no good built-in way to assign a variable like that. #isExampleType is template variable and doesn't serve this purpose.
The closest thing is let in structural directives, like ngIf:
<mat-list-item role="list" *ngFor="let o of examles;" role="listitem">
<ng-container *ngIf="o.type == 'EXAMPLE_TYPE'; let isExampleType">
<span *ngIf="isExampleType"> some text</span>
...
</ng-container>
</mat-list-item>
However, the side effect is that it provides cloaking behaviour. Since isExampleType is expected to be truthy, o.type == 'EXAMPLE_TYPE' || ' '; let isExampleType trick won't work.
The dirty workaround is to use ngFor instead. It will work as expected but provide unreasonable performance overhead:
<mat-list-item role="list" *ngFor="let o of examles;" role="listitem">
<ng-container *ngFor="let isExampleType of [o.type == 'EXAMPLE_TYPE']">
<span *ngIf="isExampleType"> some text</span>
...
</ng-container>
</mat-list-item>
A good alternative is custom ngVar structural directive, like explained here.
You can try something like:
<input #myHiddenValue type="hidden" value="ASDFG">
<div *ngIf="myHiddenValue.value==='ASDFG'">{{ myHiddenValue.value }}</div>
I am attempting to filter a list of items the code below worded fine in angular js on the web but we can't expect Ionic to work now can we?
<ion-list *ngIf="items.length">
{{items[0].title}}
<ion-item ng-repeat="item in items | filter:searchLog">
{{item == undefined}}
<!--<ion-icon name="clipboard" item-left></ion-icon>
<h2><b>Title: {{item.title}}</b></h2>
<h3><b>Caller: {{item.caller.name}} - {{item.caller.number}}</b></h3>
<h3><b>Location: {{item.caller.location}}</b></h3>
<h3><i>Dispatcher: </i>{{item.dispatcher.name}} at {{item.timeStamp}}</h3>
<h3><b>Dropped: {{item.canceled}}</b></h3>
<h3 style="white-space: normal;"><i>Details:</i> {{item.details}}</h3>-->
</ion-item>
</ion-list>
This is what my screen shows:
car out of gas
true
For the life of me I cannot understand this because if I print {{ items[0].title }} it works fine in the repeat list meaning that it is not giving me this item object back from the ng-repeat call. What is even weirder is that *ngFor works but I cannot filter it :-( Please help
TL;DR: ng-repeat in angular is returning one undefined object.
Use *ngFor with pipe (i.e. filter). If it is still not working then there is some problem with your pipe (filter). Code should look like below:
<ion-list *ngIf="items.length">
{{items[0].title}}
<ion-item *ngFor="let item of items | searchLog">
<ion-icon name="clipboard" item-left></ion-icon>
<h2><b>Title: {{item.title}}</b></h2>
<h3><b>Caller: {{item.caller.name}} - {{item.caller.number}}</b></h3>
<h3><b>Location: {{item.caller.location}}</b></h3>
<h3><i>Dispatcher: </i>{{item.dispatcher.name}} at {{item.timeStamp}}</h3>
<h3><b>Dropped: {{item.canceled}}</b></h3>
<h3 style="white-space: normal;"><i>Details:</i> {{item.details}}</h3>
</ion-item>
</ion-list>
I am trying to use ngIf within an ngFor but it's just breaking my code. Below is my code:
<ion-row *ngIf="{{i % 3}}===0" *ngFor="let category of categories; let i=index">
I need to check if the index mod 3 is equal to zero
You can overwrite your code like:
<ion-row *ngFor="let category of categories; let i=index">
<ng-container *ngIf="{{i % 3}}===0">
...
</ng-container>
</ion-row>
ng-container behaves the same as template but you can use common syntax like *ngIf and *ngFor
you can't put ngIf on the same component as ngFor
Angular disallows such construction
Using i before initializing it in ngFor will never work
If you *ngIf gets a false value the *ngFor would never be created in the first place - see point 1:-)