Angular: check if one of the ng-content slots provided - html

I have component template with multiple ng-content elements:
<div class="form__general">
<ng-content select="[general]"></ng-content>
</div>
<div class="form__footer">
<ng-content select="[footer]"></ng-content>
</div>
How can I check inside *ngIf condition is #footer is provided?
I tried something like this, but this does not work:
<div *ngIf="#footer" class="form__footer">
<ng-content select="[footer]"></ng-content>
</div>

Remove # from the condition check.
Sample Code Snippet:
app.component.html
<h1 #footer>Welcome</h1>
<child-comp>
<div *ngIf="footer.innerText === 'Welcome'" class="form__footer">
Hi There
</div>
</child-comp>
child.component.html
<ng-content select=".form__footer"></ng-content>

Related

Angular, ng-templates with if condition

I want to call for two separate templates according to role id changes. I can get my role which role as
ngIf="rolet.role.id== adminRoleId
two templates are,
<ng-template #role ></ng-template>
and
<ng-template #admin ></ng-template>
I really don't know how many role in your project. But if you want to use two ng-template,check and test with the following code.
<div *ngIf="ngIf="rolet.role.id== adminRoleId; then #role else #admin"></div>
<ng-template #role>
...
</ng-template>
<ng-template #admin>
....
</ng-template>
You can always use a switch case.
It's faster and say cleaner (personal opinion)
<div [ngSwitch]="num">
<div *ngSwitchCase="'1'">One</div>
<div *ngSwitchCase="'2'">Two</div>
<div *ngSwitchCase="'3'">Three</div>
<div *ngSwitchCase="'4'">Four</div>
<div *ngSwitchCase="'5'">Five</div>
<div *ngSwitchDefault>This is Default</div>
</div>
I put them in separate div tags like this
<div *ngIf="rolet.role.id== adminRoleId">
<ng-template #adimn></ng-template>
</div>
<div *ngIf="rolet.role.id!= adminRoleId">
<ng-template #role></ng-template>
</div>

Using ng-content with *ngtemplateOutlet not show in DOM

I have three Angular component, one base component and two child component (child1 and child2), with these structure:
child1.component.html
<ng-template #child1Template>
<div>
<h1>CHILD 1</h1>
</div>
</ng-template>
child2.component.html
<ng-template #child2Template>
<div>
<h1>CHILD 2</h1>
</div>
</ng-template>
base.component.html
<app-child1 #wrapper_child1 class="hidden"></app-child1>
<app-child2 #wrapper_child2 class="hidden"></app-child2>
<div class="baseContainer">
<ng-content *ngTemplateOutlet="wrapper_child1.child1Template"></ng-content>
<ng-content *ngTemplateOutlet="wrapper_child2.child1Template"></ng-content>
</div>
When I inspect the DOM, it shows child1 correctly but child2 not appears and there is that
<!--bindings={
"ng-reflect-ng-template-outlet": "[object Object]"
}-->
Anyone has some explenation?
Please note that my structure absolutely needs this structure because I need to insert the content of childs in the base component WITHOUT adding additional html tags.
Thanks!
Thanks to Vovan_Super I solved my issue adding this line of code in childs component
#ViewChild('child1Template') child1Template: TemplateRef<any>;

Add class with [ngClass] depending on local html condition

I have used [ngClass] in the past, applying classes depending on the Boolean value of a variable held in the javascript/typescript before. However I am wondering if it is possible to apply it based on a local HTML boolean value or not?
ie.
<div class="card" *ngFor="let item of data" #panel ngClass="{expanded: isExpanded}">
<div class="header">
<div class="itemName">Text</div>
<div class="itemDir">Some more text</div>
<mat-icon *ngIf="!panel.isExpanded" (click)="panel.isExpanded=true">edit</mat-icon>
<mat-icon *ngIf="panel.isExpanded" (click)="panel.isExpanded=false">cancel</mat-icon>
</div>
</div>
Here, I am displaying one of two icons, depending on the local isExpanded variable defined within the HTML and not the backend.
I am wanting to apply a class based on this value... is it possible?
Here is what I am working on
use like [class.expanded]="isExpanded". binding to class.expanded trumps the class attribute
<div class="card" *ngFor="let item of data" #panel [class.expanded]="panel.isExpanded" [class.notExpanded]="!panel.isExpanded">
you can use *ngIf="true as isExpanded" to make variable on the template
<div class="card" *ngFor="let item of [1,2,3,4];" >
<div class="header" *ngIf="true as isExpanded" ngClass="{expanded: !isExpanded}">
<div class="itemName">Text</div>
<div class="itemDir">Some more text</div>
<div *ngIf="isExpanded" (click)="isExpanded=!isExpanded">edit</div>
<div *ngIf="!isExpanded" (click)="isExpanded=!isExpanded">cancel</div>
</div>
</div>
stackblitz demo 👍👍
<div class="card" *ngFor="let item of data" #panel ngClass="{expanded: isExpanded}">
<div class="header">
<div class="itemName">{{item.name}}</div>
<div class="itemDir">{{item.directory}}</div>
<mat-icon *ngIf="!isExpanded;else other_content" (click)="isExpanded=true">edit</mat-icon>
<ng-template #other_content>Other Icon goes here</ng-template>
</div>
You can refer the above code which use If and else by template referenced variable which properly toggle between both icon and non Icon

Setting the div in angular to different color on click

So though my question might sound familiar the case is a bit different. I have a screen with multiple tasks. To show the tasks I am iterating via the data and my code looks something like
<div *ngFor="let task of tasks" class="scheduleContainer inline-block shadow">
<div id="myHeader" #myHeader class="activeHeader">
{{task.title}}
</div>
<div class="detailsBox">
<div class="row">
<div class="offset-md-1 col-md-auto">
Last Date:
</div>
<div class="col-md-auto">
{{task.lastDate}}
</div>
</div>
<div class="row">
<div class="offset-md-1 col-md-auto">
Duration:
</div>
<div class="col-md-auto">
{{task.duration}}
</div>
</div>
<div class="row">
<div class="offset-md-1 col-md-auto">
Total Runs:
</div>
<div class="col-md-auto">
{{task.totalRun}}
</div>
</div>
</div>
<div class="footer">
<a [routerLink]="['edit-scheduled-tasks']">edit schedule</a>
<a [routerLink]="['view-history-scheduled-tasks']">view history</a>
<a (click)="onClick()">enable task</a>
run now
</div>
</div>
<router-outlet></router-outlet>
Now when I click on the enabled task, I would like the color of that particular div to be changed. In my component, I tried something like
onClick() {
this.myHeader.nativeElement.style.background = 'red';
}
So this did change the color but it did not change the current task but rather some other task. Suggestions?
you can access myHeader from template so you can change the color something like this
<div id="myHeader" #myHeader class="activeHeader">
Change the color by myHeader variable
</div>
<button (click)="myHeader.style.background='red'">click</button>
or you can use a property with ngStyle like this
<div [ngStyle]="{'background-color':color}" >
Another way by ngStyle
</div>
<button (click)="color='red'">click</button>
or you can use a property to toggle class with ngClass
<div [ngClass]="{'red':isClicked}" >
Set class
</div>
<button (click)="isClicked=!isClicked">Toggle class</button>
Example toggle color of taskList by useing ngClass
template
<div *ngFor="let task of taskList"
[ngClass]="{'red':selectedTasks[task.id]}"
(click)="selectedTasks[task.id]= !selectedTasks[task.id]" class="task">
{{task.name}}
</div>
or you can use button to toggle the state
<div *ngFor="let task of taskList"
[ngClass]="{'red':selectedTasks[task.id]}"
class="task">
{{task.name}}
<button (click)="selectedTasks[task.id]= !selectedTasks[task.id]">toggle {{task.name}}</button>
</div>
if you want to set the state without toggle on click event just set
the state to true like this selectedTasks[task.id] =true
component
taskList =[
{id:1 , name:'Task 01'},
{id:2 , name:'Task 02'},
{id:3 , name:'Task 03'},
{id:4 , name:'Task 04'},
{id:5 , name:'Task 05'},
];
selectedTasks = {};
stackblitz demo
Not a clean way to do, but it still works. Send an index of selected element to onClick(i) and add the color to selected div. So that you don't mess with template reference.
html
<div *ngFor="let task of tasks; let i=index;" class="scheduleContainer inline-block shadow">
<div id="myHeader" #myHeader class="activeHeader">
{{task}}
</div>
<div class="footer">
<a (click)="onClick(i)">enable task</a>
</div>
</div>
component.ts
onClick(index: number) {
document.querySelectorAll('#myHeader')[index]
.style.background = 'red';
}
DEMO
It's not a good practice to manipulate DOM directly.
Angular: Stop manipulating DOM with ElementRef!
As an alternate, It's easy to bind inline style in your Angular templates using style binding.
Since you would like the color of that particular div to be changed. Use A boolean array:
component:
export class AppComponent {
name = 'Angular';
public styleArray=new Array<boolean>(10);
onClick(i)
{
this.styleArray[i]=true;
}
}
While Iterating pass index to onClick(i) to set particular index of array true and apply style dynamically
[style.color]="styleArray[i] ? 'green':'black'"
<div *ngFor="let task of tasks; let i=index" class="scheduleContainer inline-block shadow">
<div id="myHeader" [style.color]="styleArray[i] ? 'green':'black'" class="activeHeader">
{{task.title}}
</div>
........rest of the code
<a (click)="onClick(i)">enable task</a>
Live Demo

How change component html template in angular 2?

For example I have this component with a simple template:
<div>
<h2>Hello!!!</h2>
</div>
and I want to add this new template tag:
<div>
<h2>Hello!!!</h2>
<div class = "new-tag">
</div>
</div>
How can I do this?
Thanks.
Use a structural directive like *ngIf
<div>
<h2>Hello!!!</h2>
<div *ngIf="showNew" class = "new-tag"></div>
<button (click)="showNew = true">click me</button>
</div>