How to pass query param in http get

4.3k views Asked by At

I want to append query parameter to get url in angular my query parameter is

filter={"page_name":{"_eq":"login"},"environment":{"_eq":"staging"}}

where it needs to encode to

filter=%7B%22page_name%22%3A%7B%22_eq%22%3A%22login%22%7D%2C%22environment%22%3A%7B%22_eq%22%3A%22staging%22%7D%7D

It is a 3rd party API and no POST request can be made

My angular code looks like below

const urlString: URLEncode = {
      filter: {
        page_name: { _eq: pageName },
        environment: { _eq: environment.name },
      },
    };
    const paramString = encodeURIComponent(JSON.stringify(urlString.filter));

    const params = new HttpParams().set(
      'fields',
      'page_name,block_name,id,block_content'
    );
    const staticContent$: Observable<DirectusList> = this.http
      .get<DirectusList>(
        `${this.apiService.directusURL}content?filter=${paramString}`,
        { params }
      );

I am not sure this is the right way to do or not but this works. But I don't want to use 2 methods like creating http params also appending to URL instead I want to achieve it by httpParams.

Please let me know is there an easy mechanism to achieve this.

1

There are 1 answers

2
Krenom On

Without checking anything in particular, off the top of my head, I'd say that you shouldn't need to do half the work you are. The HttpClient is quite capable of taking full objects as params - whether it adequately URLEncodes them is another matter (one hopes they do).

So long as you have a filter object, you should be able to directly put that into the mix wherein the client should handling JSONifying it and whatnot:


const filter = {
  page_name: { _eq: pageName },
  environment: { _eq: environment.name },
};


let params = new HttpParams();
params = params.set('fields', 'page_name,block_name,id,block_content');
params = params.set('filter', filter);

const embarkStaticContent$: Observable<DirectusList> = this.http
  .get<DirectusList>(
    `${this.apiService.directusEmbarkURL}embark_content`,
    { params }
);

Edit: Hmm, seems you can't just give it filter as an object - I guess quick fix really is to JSON.stringify(filter).

As another example, however - here's a version that I've got in use in several projects - wrapper around the HttpClient such that we don't interact with it directly and it handles all of the nitty gritty that you shouldn't have to worry about every time you make some API request.

Removed the various log messages and thus can ignore the notification and logger services and whatnot, the main mechanism is there:

/*
  Example usage:
      ...get('controller/action', { param1: 123, param2: 'secondParam' })
  Produces the request:
      "baseUrl/controller/action?param1=123&param2=secondParam"
*/
public get<T>(apiResource: string, queryParams?: any): Observable<ActionResponsePayloadDto<T>> {
  const url = this.constructUrl(apiResource);

  return this.httpClient.get<ActionResponsePayloadDto<T>>(url, { params: this.encodeQueryParams(queryParams) })
      .pipe(catchError((err) => this.handleError(err, this.notification, this.logger, this.logSystems)));
}

// Handle transforming any data types as required here for the query
// params before being turned into HttpParams objects
private encodeQueryParams(queryParams: any): HttpParams {
  let result = new HttpParams();

  if (!queryParams) { return result; }

  Object.keys(queryParams).forEach((key: string) => {
    let val = queryParams[key];

    if (this.objectHelper.isDate(val)) {
      val = val.toIsoString();
    }

    result = result.set(key, val);
  });

  return result;
}

The only thing we do, really, is transform any dates being sent into an ISO format string. There's no other stringifying going on, so I don't see why it would complain about being given your filter object as an object...

Edit #2: Oh, but another project doesn't use this wrapper, here's an example of its param usage with raw HttpClient:

public getAlert(alertHash: string): void {
  const sub = this.http.get(this.alertUrl, {params: {alertHash}})
    .subscribe((response: DeviceDetailsAlertDto) => {
      sub.unsubscribe();
      this.emit(this.alertObs, response);
      },
      (err: any) => {
        sub.unsubscribe();
        console.error(`Error retreiving alert details: ${err}`);
        this.emit(this.alertObs, undefined);
      });
}

I suspect maybe avoid playing with the HttpParams object if you don't need to.. I think just putting together your query params as a single object might work?

const queryParams = {
  fields: 'page_name,block_name,id,block_content',
  filter: {
    page_name: { _eq: pageName },
    environment: { _eq: environment.name },
  }
};

const staticContent$: Observable<DirectusList> = this.http
  .get<DirectusList>(
    `${this.apiService.directusURL}content`,
    { params: queryParams }
  );