I am confused whether it's possible to make api call onInit component and evry time when parent gets event from child (pagination component), call api with new pageSize and pageNumber and assign this data. Main problem is that i want to avoid manually unsubscribe, and effect (beacuse it's not recomended to use it to change state).Maybe at this time there is no other option that unsubscribe. My next question is, is it more recommended to use a model instead of input and output signals?
child component ts
rows = input.required<number>();
pageChanged = output<number>();
onPageChange(event: PaginatorState) {
this.pageChanged.emit(event.rows!);
}
parent component html
<app-paginator
[rows]="pageSize()"
(pageChanged)="onPageChange($event)"
[totalRecords]="dataResponse()?.totalElements || 0"
[(paginationData)]="pagination"
[rowsPerPageOptions]="allowedNumbersOfRecordOnOnePage"></app-paginator>
parent component ts
pageNumber = signal<number>(0);
pageSize = signal<number>(100);
//apiService.getData(arg1,arg2) return observable
dataResponse= toSignal(
this.apiService.getData(this.pageNumber(), this.pageSize())
);
onPageChange(pageSize: number) {
this.pageSize.set(pageSize);
// How to set data to dataResponse reactively to signal without manually unsubscribe?
}
There are multiple ways to achieve it.
toObservable()
You can convert your signals to Observables using toObservable()
(developer preview). Use combineLatest()
to combine them and and switchMap()
to trigger the API requests:
pageNumber = signal<number>(0);
pageSize = signal<number>(100);
data$ = combineLatest(
toObservable(this.pageNumber),
toObservable(this.pageSize)
).pipe(
switchMap(([pageNumber, pageSize]) =>
this.apiService.getData(pageNumber, pageSize)
),
);
dataResponse = toSignal(data$);
resource()
Since Angular 19 you can use the experimental resource()
function which allows asynchronous handling with Signals. While the base resource()
function only supports Promises, you can also use the rxResource()
function which supports Observables:
import { rxResource } from '@angular/core/rxjs-interop';
pageNumber = signal<number>(0);
pageSize = signal<number>(100);
dataResource = rxResource({
request: () => ({
pageNumber: this.pageNumber(),
pageSize: this.pageSize(),
}),
loader: ({ request }) => {
const { pageNumber, pageSize } = request;
return this.apiService.getData(pageNumber, pageSize);
},
});