Reputation: 2712
I need my component template to render an email address which may is stored in one property of a class, but should fall back to another propery in case the first is null or empty. So I implemented it this way:
my-component.html
:
<p>{{ myService.usuario.emailAddress() }}</p>
my-component.ts
:
export class MyComponent implements OnInit {
constructor(private myService: MyService) {
}
}
my-service.ts
:
export class MyService {
//...
public user: User;
//...
}
user.ts
:
export class User {
//...
mail: string;
userPrincipalName: string;
public emailAddress(): string {
return this.mail || this.userPrincipalName;
}
//..
}
But then the email won't be rendered. However, if I put this inside the template:
<p>{{ myService.usuario.mail || myService.usuario.userPrincipalName }}</p>
Then it will be rendered as intended.
Returnin this.mail ? this.mail : this.userPrincipalName
instead of this.mail || this.userPrincipalName
did no good either...
In order to better understand what's going on, I changed the template to this:
<p>.mail = {{ azureService.usuario.mail}}</p>
<p>.userPrincipalName = {{ azureService.usuario.userPrincipalName}}</p>
<p>(.mail || .userPrincipalName) = {{ azureService.usuario.mail || azureService.usuario.userPrincipalName}}</p>
<p>.emailAddress() = {{ azureService.usuario.emailAddress()}}</p>
This was the result:
.mail = [email protected]
.userPrincipalName = [email protected]
(.mail || .userPrincipalName) = [email protected]
.emailAddress() =
So...
Is Angular template limited to reading properties but incapable of reading functions' results, as it seems? Or did I something wrong anywhere?
Upvotes: 1
Views: 892
Reputation: 6976
As mentioned in my comment above, if Angular calls emailAddress
before mail
and userPrincipalName
are set, then there is no way for Angular to know that those properties have changed and that it needs to call emailAddress
again. The behavior you are looking for is certainly attainable in an Angular application using RxJs. Maybe a good introduction read is Observables in the Angular documentation. I have added some sample code to help you get an idea for what you will need to solve your problem:
import { HttpClient } from '@angular/common/http';
import { Observable} from 'rxjs';
import { map} from 'rxjs/operators';
export class MyService {
constructor(httpClient: HttpClient) {}
user(): Observable<User> {
return this.httpClient.get('user/end/point');
}
username(): Observable<string> {
return this.user().pipe(
map(user => user.mail || user.principalName)
);
}
}
export class MyComponent implements OnInit {
username = this.myService.username();
constructor(private myService: MyService) { }
}
<p>{{ username | async }}</p>
The async pipe subscribes to the username
observable and displays the result.
Upvotes: 1