I have a school project where i use angular CLI 15 and i need to pass data through the router. I need to pass the variable isAdmin from appComponent to tipsListComponent. appComponent is always displayed and the default route displays tipListComponent inside appComponent.
app.component.ts :
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
public isAdmin = true;
public isConnected = false;
title = 'Terraria';
}
app.component.html :
<mat-toolbar>
<div id="centered">
<img src="../assets/logo.png" id="logo" routerLink="/" />
</div>
<div id="right_nav">
<button
[hidden]="isConnected"
mat-flat-button
color="grey"
style="background-color: #666b6f; color: white"
routerLink="/login"
>
Se connecter
</button>
<button
[hidden]="isConnected"
mat-flat-button
color="grey"
style="margin-left: 4px; background-color: #666b6f; color: white"
routerLinkActive="activebutton"
routerLink="/register"
>
S'enregistrer
</button>
<button
[hidden]="!isAdmin"
mat-flat-button
color="grey"
style="margin-left: 4px; background-color: #666b6f; color: white"
matTooltip="Outils d'administration"
>
<mat-icon>build</mat-icon>
</button>
<button
[hidden]="!isConnected"
mat-flat-button
color="grey"
style="margin-left: 4px; background-color: #666b6f; color: white"
(click)="isConnected = !isConnected"
matTooltip="Se déconnecter"
>
<mat-icon>exit_to_app</mat-icon>
</button>
</div>
</mat-toolbar>
<div id="sapcing" style="height: 85px"></div>
<div id="body">
<router-outlet></router-outlet>
</div>
tip-List.component.ts :
import { Component, Input } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Sort } from '@angular/material/sort';
@Component({
selector: 'app-tips-list',
templateUrl: './tips-list.component.html',
styleUrls: ['./tips-list.component.css'],
})
export class TipsListComponent {
searchTitle = '';
searchAuthor = '';
searchTag = '';
disableThirdHeader = false;
tips = [
{ name: 'Frozen yogurt', tags: '159', author: 'admin' },
{name: 'Ice cream sandwich',tags: '237',author: 'admin',},
{ name: 'Eclair', tags: '262', author: 'admin' },
{ name: 'Cupcake', tags: '305', author: 'admin' },
{ name: 'Gingerbread', tags: '356', author: 'user' },
];
sortedData = this.tips.slice();
sortData(sort: Sort) {
const data = this.tips.slice();
if (!sort.active || sort.direction === '') {
this.sortedData = data;
} else {
this.sortedData = data.sort((a, b) => {
const aValue = (a as any)[sort.active];
const bValue = (b as any)[sort.active];
return (aValue < bValue ? -1 : 1) * (sort.direction === 'asc' ? 1 : -1);
});
}
}
}
tip-List.component.html :
<mat-form-field >
<mat-label>Rechercher titre</mat-label>
<input
matInput
placeholder="Ex : Œil de cthulhu"
[(ngModel)]="searchTitle"
autocomplete="off"
/>
</mat-form-field>
<mat-form-field >
<mat-label>Rechercher tag</mat-label>
<input
matInput
placeholder="Ex : Œil de cthulhu"
[(ngModel)]="searchTag"
autocomplete="off"
/>
</mat-form-field>
<mat-form-field >
<mat-label>Rechercher auteur</mat-label>
<input
matInput
placeholder="Ex : Œil de cthulhu"
[(ngModel)]="searchAuthor"
autocomplete="off"
/>
</mat-form-field>
<table matSort (matSortChange)="sortData($event)">
<tr>
<th mat-sort-header="name">Titre</th>
<th mat-sort-header="tags">Tags</th>
<th mat-sort-header="author">Auteur</th>
</tr>
<tr
*ngFor="
let tip of sortedData
| filter : searchTitle
| filterTags : searchTag
| filterAuthor : searchAuthor
"
>
<td>{{ tip.name }}</td>
<td>{{ tip.tags }}</td>
<td>{{ tip.author }}</td>
<button mat-icon-button>
<mat-icon color="warn" *ngIf="isAdmin">delete</mat-icon>
</button>
</tr>
</table>
i want the last button to appear only if isAdmin from appComponent is true
I've tried importing isAdmin to the component and using route parameters
CodePudding user response:
Since probably more than one component needs to have access to the value of isAdmin
, you should assign this value to a variable in a service, and inject the service in every component you need the value.
Since the value of isAdmin
could change - e.g. after logging in - and would probably come from an HTTP request, you should use an Observable
to hold the value.
It could look like this:
session.service.ts:
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SessionService {
public isAdmin: Observable<boolean> = of(true)
}
any component that needs the value of isAdmin
:
import { Observable } from 'rxjs';
@Component()
export class TipListComponent {
public isAdmin: Observable<boolean> = this.sessionService.isAdmin
constructor(
private readonly sessionService: SessionService
) {
}
}
in the component template:
<div *ngIf="isAdmin | async">This user is an admin!</div>
CodePudding user response:
What you are looking for is called @Input
and @Output
. Each component can have an @Input
which is essentially a custom property you can set via the html such as:
--- my-custom-component.ts
@Component()
export class MyCustomComponent {
@Input()
isAdmin: boolean = false; // default value, in case it was not configured in the html.
}
--- appComponent.html
<my-custom-component [isAdmin]="myVariable"></my-custom-component>
You can find the full explanation in the Angular Documentation along with a full step-by-step example.