如何在Angular 14应用中将变量从Service传递到分页库?
1. Input Binding with Reactive Updates
This is the most straightforward approach. Instead of letting the pagination component depend on your ProductService, pass the search params directly via an @Input() property. To handle dynamic updates when search params change, use a BehaviorSubject in your service to emit changes.
Step 1: Update ProductService to emit reactive search params
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ProductService { private searchParamsSubject = new BehaviorSubject<Record<string, any>>({}); public searchParams$ = this.searchParamsSubject.asObservable(); setSearchParams(params: Record<string, any>) { this.searchParamsSubject.next(params); } }
Step 2: Pass params to Pagination component from ProductListComponent
In your product list component, subscribe to the reactive search params and bind them to the pagination component's input:
import { Component, OnInit } from '@angular/core'; import { ProductService } from './product.service'; @Component({ selector: 'app-product-list', template: ` <!-- Your search UI with ngModel bindings --> <app-pagination [searchParams]="currentSearchParams"></app-pagination> ` }) export class ProductListComponent implements OnInit { currentSearchParams: Record<string, any> = {}; constructor(private productService: ProductService) {} ngOnInit() { this.productService.searchParams$.subscribe(params => { this.currentSearchParams = params; }); } }
Step 3: Accept input in Pagination component
Update the pagination component to receive and use the search params:
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-pagination', template: `<!-- Pagination UI logic here -->` }) export class PaginationComponent { @Input() searchParams: Record<string, any> = {}; // Example: Use params when fetching a new page loadPage(pageNumber: number) { // Build API request using this.searchParams console.log('Fetching page', pageNumber, 'with params:', this.searchParams); } }
2. Use an Injection Token for Decoupled Access
If you want to keep the pagination component reusable without tight coupling to ProductService, use an Angular injection token to provide the search params observable.
Step 1: Define a shared injection token
Create a separate file for shared tokens:
import { InjectionToken } from '@angular/core'; import { Observable } from 'rxjs'; export const SEARCH_PARAMS_OBSERVABLE = new InjectionToken<Observable<Record<string, any>>>( 'Observable of search parameters' );
Step 2: Provide the token in your app module
In your root module, provide the token using the ProductService's observable:
import { NgModule } from '@angular/core'; import { SEARCH_PARAMS_OBSERVABLE } from './shared/tokens'; import { ProductService } from './product.service'; @NgModule({ providers: [ { provide: SEARCH_PARAMS_OBSERVABLE, useFactory: (productService: ProductService) => productService.searchParams$, deps: [ProductService] } ] }) export class AppModule {}
Step 3: Inject the token in Pagination component
Now the pagination component can inject the token without knowing about ProductService:
import { Component, Inject, OnInit } from '@angular/core'; import { SEARCH_PARAMS_OBSERVABLE } from './shared/tokens'; import { Observable } from 'rxjs'; @Component({ selector: 'app-pagination', template: `<!-- Pagination UI logic here -->` }) export class PaginationComponent implements OnInit { searchParams$: Observable<Record<string, any>>; constructor(@Inject(SEARCH_PARAMS_OBSERVABLE) searchParams$: Observable<Record<string, any>>) { this.searchParams$ = searchParams$; } ngOnInit() { this.searchParams$.subscribe(params => { // Update pagination logic when params change console.log('Updated search params:', params); }); } }
3. Delegate Data Fetching to Parent Component
If your pagination component handles API calls, instead of passing params directly, pass a callback function that fetches data with the correct search params. This keeps the pagination component completely unaware of your search logic.
Step 1: Define fetch callback in ProductListComponent
import { Component } from '@angular/core'; import { ProductService } from './product.service'; import { Observable } from 'rxjs'; @Component({ selector: 'app-product-list', template: ` <!-- Your search UI --> <app-pagination [fetchPage]="fetchPage"></app-pagination> ` }) export class ProductListComponent { constructor(private productService: ProductService) {} // Callback function that pagination can call to fetch pages fetchPage = (pageNumber: number, pageSize: number): Observable<any> => { const currentParams = this.productService.getCurrentSearchParams(); // Or get from observable return this.productService.getProducts(pageNumber, pageSize, currentParams); }; }
Step 2: Use the callback in Pagination component
import { Component, Input } from '@angular/core'; import { Observable } from 'rxjs'; @Component({ selector: 'app-pagination', template: ` <button (click)="onPageChange(1)">Page 1</button> <!-- Other pagination controls --> ` }) export class PaginationComponent { @Input() fetchPage!: (page: number, size: number) => Observable<any>; onPageChange(pageNumber: number) { this.fetchPage(pageNumber, 10).subscribe(data => { // Update pagination state with fetched data console.log('Fetched page data:', data); }); } }
内容的提问来源于stack exchange,提问作者Razvan Zamfir

