You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合Resolve使用QueryParams实现汽车搜索功能?

Let's fix your code step by step, addressing all the issues that are preventing your search and resolve flow from working correctly:

Key Issues in Your Current Code

  1. Typo in UserService: You're referencing jobListSub instead of carListSub when creating the Observable, breaking the Subject subscription chain.
  2. Resolver Misuse: Your resolver just returns an existing Observable instead of fetching fresh data from the API using route parameters—this fails on page refreshes or direct navigation to /cars.
  3. Mismatched Method Names: Your component calls searchbycategory() but your service defines searchCars().
  4. API Parameter Mismatches: Headers in searchCars() use incorrect parameter names (pageNumber instead of pageNo, options.year instead of options.launchYear).
  5. Redundant Subject Dependency: Resolvers should directly return API request Observables to guarantee data is ready before the route activates.

Corrected Code

1. UserService

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
import { map } from 'rxjs/operators';

interface ApiResponse {
  data: any[];
}

@Injectable({ providedIn: 'root' })
export class UserService {
  carListSub: Subject<any[]> = new Subject();
  carListData: Observable<any[]>;

  constructor(private http: HttpClient) {
    // Fix typo: jobListSub → carListSub
    this.carListData = this.carListSub.asObservable();
  }

  // For component-initiated searches (feeds the Subject for reuse)
  searchCars(options: { pageNo: number, pageSize: number, companyName: string, launchYear: string }): Observable<any[]> {
    const httpOptions = this.buildHeaders(options);
    
    return this.http.get<ApiResponse>('/api/user/getsearchedCars', httpOptions).pipe(
      map(res => res.data),
      map(data => {
        this.carListSub.next(data); // Push data to subscribers
        return data;
      })
    );
  }

  // For resolver to fetch fresh data using route params
  getFilteredCars(options: { pageNo: number, pageSize: number, companyName: string, launchYear: string }): Observable<any[]> {
    const httpOptions = this.buildHeaders(options);
    
    return this.http.get<ApiResponse>('/api/user/getsearchedCars', httpOptions).pipe(
      map(res => res.data)
    );
  }

  // Helper to avoid code duplication for headers
  private buildHeaders(options: { pageNo: number, pageSize: number, companyName: string, launchYear: string }) {
    return {
      headers: new HttpHeaders({
        'pageSize': options.pageSize.toString(),
        'pageNo': options.pageNo.toString(), // Match route param name
        'companyName': options.companyName,
        'launchYear': options.launchYear // Match component's options key
      })
    };
  }
}

2. CarListResolver

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { UserService } from './user.service';

@Injectable({ providedIn: 'root' })
export class CarListResolver implements Resolve<any[]> {
  constructor(private userService: UserService) {}

  resolve(route: ActivatedRouteSnapshot): Observable<any[]> {
    console.log('Resolve CarList working');
    // Extract query params from the route and parse numeric values
    const options = {
      pageNo: parseInt(route.queryParamMap.get('pageNo') || '1', 10),
      pageSize: parseInt(route.queryParamMap.get('pageSize') || '10', 10),
      companyName: route.queryParamMap.get('companyName') || '',
      launchYear: route.queryParamMap.get('launchYear') || ''
    };

    // Fetch fresh data directly from API (Resolver waits for this to complete)
    return this.userService.getFilteredCars(options);
  }
}

3. SearchCar Component

searchCars() {
  const options = {
    pageNo: this.pageNo,
    pageSize: this.pageSize,
    companyName: this.companyName,
    launchYear: this.year
  };
  // Fix method name mismatch: searchbycategory → searchCars
  this.userService.searchCars(options).subscribe();
  this.router.navigate(['/cars'], { queryParams: options });
}

4. CarList Component

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-car-list',
  templateUrl: './car-list.component.html',
  styleUrls: ['./car-list.component.css']
})
export class CarListComponent implements OnInit {
  carList: any[] = [];

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    // Get resolver data directly from snapshot (no need for looped push)
    this.carList = this.route.snapshot.data['filteredCars'];

    // Optional: Subscribe if you need to react to route param changes (e.g., pagination)
    // this.route.data.subscribe((data: { filteredCars: any[] }) => {
    //   this.carList = data.filteredCars;
    // });
  }
}

5. Route Configuration (Don't Forget This!)

Make sure your resolver is attached to the /cars route:

import { Routes } from '@angular/router';
import { CarListComponent } from './car-list/car-list.component';
import { CarListResolver } from './car-list.resolver';

const routes: Routes = [
  {
    path: 'cars',
    component: CarListComponent,
    resolve: {
      filteredCars: CarListResolver
    }
  }
];

Why These Changes Work

  • Resolver Integrity: The resolver now pulls query params directly from the route and fetches fresh data, ensuring the component always has data when it loads—even on page refreshes.
  • Subject Reuse: We kept the carListSub and carListData so you can subscribe to this Observable in other components for cross-component data sharing (as you intended).
  • Cleaner Component Code: No more manual array pushing—we directly assign the resolver data to carList.
  • Consistent Parameters: Fixed all mismatched parameter names between components, services, and API headers.

内容的提问来源于stack exchange,提问作者Vasanth Kumar D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 12:08:16