I have a problem and I'm looking for a solution. In a standalone component (Angular 19) with OnPush detection in the template I want to read data from observable:
@Component({
selector: 'app-profile',
imports: [AsyncPipe],
template: `
@let userData = oidcService.getUserData() | async;
@let apiUserData = usersService.usersGet(userData.sub) | async;
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileComponent {
public readonly oidcService = inject(OidcSecurityService);
public readonly usersService = inject(UsersService);
}
UsersService:
@Injectable({
providedIn: 'root',
})
export class UsersService {
private readonly urlBase = `${environment.apiUrl}/users`;
private readonly httpClient = inject(HttpClient);
public usersGet(id: string): Observable<UserEntity> {
return this.httpClient.get<UserEntity>(`${this.urlBase}/${id}`);
}
}
The problem is that apiUserData
gets into a loop of calls instead of asking only once.
userData
works fine, but it returns data from the service without http.
Why does this happen?
I have a problem and I'm looking for a solution. In a standalone component (Angular 19) with OnPush detection in the template I want to read data from observable:
@Component({
selector: 'app-profile',
imports: [AsyncPipe],
template: `
@let userData = oidcService.getUserData() | async;
@let apiUserData = usersService.usersGet(userData.sub) | async;
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileComponent {
public readonly oidcService = inject(OidcSecurityService);
public readonly usersService = inject(UsersService);
}
UsersService:
@Injectable({
providedIn: 'root',
})
export class UsersService {
private readonly urlBase = `${environment.apiUrl}/users`;
private readonly httpClient = inject(HttpClient);
public usersGet(id: string): Observable<UserEntity> {
return this.httpClient.get<UserEntity>(`${this.urlBase}/${id}`);
}
}
The problem is that apiUserData
gets into a loop of calls instead of asking only once.
userData
works fine, but it returns data from the service without http.
Why does this happen?
1 Answer
Reset to default 0Since it is angular 19, use rxResource
(Directly use the service method which returns an observable) or httpResource
(Directly use the url to get the data) to achieve this.
We use toSignal
to convert the observable from oidc
to a signal.
@Component({
selector: 'app-profile',
template: `
@let userData = userData();
@let apiUserData = apiUserDataRx.value();
@let apiUserData2 = apiUserDataHttp.value();
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProfileComponent {
readonly userData = toSignal(oidcService.getUserData());
public readonly oidcService = inject(OidcSecurityService);
public readonly usersService = inject(UsersService);
apiUserDataRx = rxResource({
request: () => this.userData(),
loader: ({ request: userData }) => this.usersService.usersGet(userData.sub),
});
apiUserDataHttp = httpResource(() => `${this.urlBase}/${this.userData().sub}`);
}