2
votes

I am using mock data and InMemoryDbService as shown on the tour of heroes example. Loading data works fine when I don't pass HttpParams. Once I add params, I get a 500 response with the following error in the body: {error: "collection.filter is not a function"} I've populated my table with data from a get request as follows:

Component code:

@Component({
  selector: 'app-adapter',
  templateUrl: './adapter.component.html',
  styleUrls: ['./adapter.component.css']
})
export class AdapterComponent implements OnInit {
  dataSource = new MatTableDataSource<Request>();
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatPaginator) paginator: MatPaginator;
  constructor(private api: BaseServiceApi) {}

  ngOnInit() {
    this.refresh(); // this works with no params and populates my table
  }

  refresh(params?) {
    this.getRequests(params)
      .subscribe(reply => {
          this.dataSource.data = reply.payload as Request[];
          this.dataSource.sort = this.sort;
          this.dataSource.paginator = this.paginator;
          this.pageSize = this.paginator.pageSize;
        }
      );
  }

  getRequests(params?): Observable<ServerReply> {
    console.log(params);
    return this.api.get("requests", params);
  }

  processSearch() { // here is where I am submitting a form and trying to get new response

    if (this.searchForm.invalid)
      return;

    // these params are not fields of ServerReply or request but are filters
    let params = new HttpParams({fromObject: this.searchForm.getRawValue()});
    this.refresh(params); // this is submitting with params and throwing exception
  }

}

api service:


import { Injectable } from '@angular/core';
import {Observable, of, pipe} from "rxjs";
import {HttpClient, HttpParams} from "@angular/common/http";
import {catchError} from "rxjs/operators";
import {ServerReply} from "../../models/server-reply";

@Injectable({
  providedIn: 'root'
})
export class BaseServiceApi {

  apiUrl: string;

  constructor(private http: HttpClient) {
  }

  get(path: string, params?: HttpParams): Observable<ServerReply> {
    return this.http.get<ServerReply>(this.apiUrl + path, {params})
      //.pipe(catchError(this.handleError<ServerReply>(path, new ServerReply()))
      //);
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      // TODO: send the error to remote logging infrastructure
      console.error(operation + ": " + JSON.stringify(error)); // log to console instead

      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

}

ServerReply:

export class ServerReply {

  alerts: [];

  payload: [];

}

Request:

export class Request {
  id: number,
  // other fields omitted

}

mock data service:

@Injectable({
  providedIn: 'root'
})
export class MockDataService implements InMemoryDbService {

  createDb() {
    let requests = this.createRequests(1000);
    return {requests};
  }

  private createCloudRequests(count: number) {
    // returns one ServerReply with a Request[] in ServerReply.payload
  }
}

Not sure what I'm doing wrong. I tried adding query params in the tour of heroes examples and that works (even non existent fields of a Hero don't error out like this).

app module imports:

imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    MaterialModule,
    AppRoutingModule,
    HttpClientModule,
    HttpClientInMemoryWebApiModule.forRoot(MockDataService, {dataEncapsulation: false}),
    ReactiveFormsModule,
  ]

1
Hello, I think this can be your issue stackoverflow.com/questions/35891671/… try to modify api service with http.get(url, params).then(response => console.log(response)) to checkNikita
@Nikita My problem is during the get request. I get a 500 response. I guess it's trying to apply filter on my mock data {requests}when requests is not an array. (during the request)user1738539

1 Answers

5
votes

The issue was that by default, the InMemoryDbSerivce expects everything in the db object to be an array. It will simply try to apply filter based on my query params.

I found a solution by looking through the examples in github: https://github.com/angular/in-memory-web-api/blob/master/src/app/hero-in-mem-data-override.service.ts

Here I was able to intercept the get request and apply my own filtering using the queryparams I provided

mock service:

import {InMemoryDbService, RequestInfo, STATUS} from 'angular-in-memory-web-api';

@Injectable({
  providedIn: 'root'
})
export class MockDataService implements InMemoryDbService {
  ...

  // intercept get method for all in memory requests.
  get(reqInfo: RequestInfo) {
    let queryParams: Map<string, string[]> = reqInfo.query;
    console.log(queryParams);

    if (queryParams.size > 0) // if no params are passed, Map exists but is empty
      return this.handleFilterRequest(reqInfo, queryParams); // custom Response built here

    // return request as passthrough if no params
    return undefined;
  }

}