Reputation: 201
I have a method on a service which fetches time from the server and I plan to use it in a custom pipe. The purpose of the pipe is to compare the the a timestamp to the current time and return it in human readable format.
Service
export class TimeService{
currentServerTime;
fetchCurrentTimeStamp(){
//http request using Observable
return sendGETRequest(.....).map(data => {
this.currentServerTime = data;
return this.currentServerTime;
})
}
}
Pipe
export class GetTimeFromNowPipe implements PipeTransform{
fromNow;
currentServerTime: number;
constructor(private timeService: TimeService, private appSettings: AppSettings){}
transform(value: number){
var currentTime;
this.timeService.fetchCurrentTimestamp().subscribe(data => {
currentTime = data
if(!value) return "";
if(value){
let newDate = moment.unix(value);
this.fromNow = newDate.from(moment.unix(currentTime), true);
}
return this.fromNow;
});
}
}
HTML
<ul>
<li *ngFor = "let model of models">
<span>{{model.created | getTimeFromNow}}</span>
</li>
</ul>
I'm stuck with the Async calls. How do I return the value from the pipe only after I fetch the data from the server?
Upvotes: 3
Views: 2022
Reputation: 316
The best way to implement it is to not use the service inside the pipe. You can use custom pipe to implement only what the pipe needs to do. Your pipe needs to be defined like this:
export class GetTimeFromNowPipe implements PipeTransform{
constructor(private appSettings: AppSettings){}
transform(value: number, currentTime:number){
if(!value) return "";
else{
let newDate = moment.unix(value);
return newDate.from(moment.unix(currentTime), true);
}
}
}
inside your component you can call your service and store it inside a varible in your Oninit life cycle ( of course you need to inject the service inside the component).
serverTime:number;
ngOnInit(){
this.timeService.fetchCurrentTimestamp().subscribe(data=>this.serverTime=data);
}
and then inside the template of your component you can use you're pipe. with either
<ul *ngIf="serverTime">
<li *ngFor = "let model of models">
<span>{{model.created | getTimeFromNow:serverTime}}</span>
</li>
</ul>
Or
<ul>
<li *ngFor = "let model of models">
<span>{{model.created | getTimeFromNow: serverTime | async}}</span>
</li>
</ul>
Clarification & Purposes:
the purpose of this implementation is to facilitate:
-Testing your pipe
-easy debug in case if the serveur have problems
-an independent implementation from the server that can be used in other component with different parameters (reusability).
Upvotes: 2
Reputation: 658047
A return
is missing and subscribe
needs to be changed map
to allow the async pipe to do the subscription
return this.timeService.fetchCurrentTimestamp().map(data => {
and for async values the async pipe needs to be used
<span>{{model.created | getTimeFromNow | async }}</span>
Upvotes: 6