0

我想附加查询参数以获取 url 我的查询参数是

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

它需要编码到的地方

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

它是第 3 方 API,不能发出 POST 请求

我的角度代码如下所示

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 }
      );

我不确定这是否是正确的做法,但这是可行的。但我不想使用 2 种方法,比如创建 http 参数也附加到 URL,而是我想通过 httpParams 来实现它。

请让我知道是否有一个简单的机制来实现这一点。

4

1 回答 1

0

在没有特别检查任何事情的情况下,我会说你不应该做一半的工作。HttpClient 非常有能力将完整的对象作为参数——它是否充分地对它们进行 URLEncodes 是另一回事(希望他们这样做)。

只要您有一个filter对象,您就应该能够直接将其放入混合中,其中客户端应处理 JSON 化它等等:


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 }
);

编辑:嗯,看来你不能只是把它filter作为一个对象 - 我想快速修复真的是JSON.stringify(filter).

然而,作为另一个例子 - 这是我在几个项目中使用的一个版本 - 包装HttpClient这样我们不直接与它交互,它处理你不应该担心的所有细节每次您提出一些 API 请求时。

删除了各种日志消息,因此可以忽略通知和记录器服务等等,主要机制是:

/*
  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;
}

实际上,我们唯一要做的就是将发送的任何日期转换为 ISO 格式字符串。没有其他字符串化正在进行,所以我不明白为什么它会抱怨将您的filter对象作为对象...

编辑#2:哦,但是另一个项目不使用这个包装器,这是一个使用 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);
      });
}

HttpParams如果您不需要,我怀疑可能会避免使用该对象。我认为将您的查询参数组合为一个对象可能会起作用?

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 }
  );
于 2020-12-02T22:34:39.717 回答