【问题标题】:Implement dynamic query string from forms to handle multiple queries从表单实现动态查询字符串以处理多个查询
【发布时间】:2020-06-05 09:55:24
【问题描述】:

我在后端实现了一个端点,它根据搜索参数接受多个参数:

例如/api/transaction_report/?year=2020&month=5&subcounty=2

我有一个将过滤器参数作为输入的表单。如何根据onFilterTransactions()函数中不同的搜索过滤器组合动态创建查询字符串?

onFilterTrasactions() {

  const params = [];
  const dateFrom = this.dateFilterForm.get('fromDate').value
  const dateTo = this.dateFilterForm.get('toDate').value;
  const year = this.dateFilterForm.get('year').value;
  const month = this.dateFilterForm.get('month').value;
  const subcounty = this.dateFilterForm.get('subcounty').value;
  const ward = this.dateFilterForm.get('ward').value;
  const licenseCategoryCode = this.dateFilterForm.get('licenseCategoryCode').value;

  const formItems = [ dateFrom, dateTo, year, month, subcounty, ward, licenseCategoryCode ];

  for (const item of formItems) {

    if (item != null) {
      params.push(item);
    }


  }
  console.log(dateFrom)
  // console.log(this.dateFilterForm.value);


}

表单控件 例如,只想按月过滤,因此,其余的表单值最终将是null

this.dateFilterForm = new FormGroup({
  fromDate: new FormControl(),
  toDate: new FormControl(),
  year: new FormControl(),
  month: new FormControl(),
  subcounty: new FormControl(),
  ward: new FormControl(),
  licenseCategoryCode: new FormControl(),

});

过滤器屏幕截图

搜索服务

  getAllFilteredTransactions(query) {
    return this.http.get<any>(`${environment.apiUrl}/api/transactions/filter_report/?${query}=`, {
      headers: this.headers
    });
  }

【问题讨论】:

  • 所以你想构建你的query 字符串,比如fromDate=...&amp;toDate=...&amp;year=... 等等?
  • @VRoxa 是的

标签: angular typescript


【解决方案1】:

我们可以分两步完成。

首先,将参数列表构建为一个键值对数组

type KeyValue<T> = [string, T];

const getKVPairs = (form: any, ...keys: string[]): KeyValue<any>[] =>
    keys.map(key => {
        const value = form.get(key).value;
        return [ key, value ];
    });

基本上,它使用从表单本身提取的键和值构建对的集合。

之后您可以过滤此集合

// Parameter list
const keys = ['fromDate', 'toDate', 'year'];
const kvs = getKVPairs(form, ...keys);

// Check for value truthiness
const filtered = kvs.filter(([, value]) => !!value);

然后,是时候基于对集合构建查询了。

const buildQuery = (...params: KeyValue<any>[]) => {
    const concat = (([key, value]): KeyValue<any>) =>
        `${key}=${value}`;

    // Creates the string list like
    // [ key=value , key=value ]
    const fields = params.map(concat);
    // Then joins with an '&' in between
    return fields.join('&');
}

我认为它应该是一个服务本身,可以作为对组件的依赖注入。
但是,使用它的功能方式是

const keys = ['fromDate', 'toDate', 'year'];
const kvs = getKVPairs(form, ...keys);
const filtered = kvs.filter(([, value]) => !!value);
const query = buildQuery(...filtered);

console.log(query); // fromDate=1&toDate=1&year=1

例如,假设所有值都是1

编辑:

过滤器可能更复杂。我只是提供了一个非常短的方法......但是,这可以是任何功能,如

const filter = (pairs: KeyValue<any>[], condition: (pair: KeyValue<any>) => boolean) =>
    pairs.filter(condition);

在有服务的情况下使其灵活。

此外,服务会像

@Injectable({...})
export class QueryBuilder {

    constructor(/* dependencies if needed */) {  }

    public build = (form: any, condition: (pair: KeyValue<any>) => boolean, ...keys: string[]) => {
        const kvs = this.getKVPairs(form, ...keys);
        const filtered = kvs.filter(condition);
        return this.buildQuery(...filtered);
    }

    private getKVPairs = (form: any, ...keys: string[]): KeyValue<any>[] =>
        keys.map(key => {
            const value = form.get(key).value;
            return [ key, value ];
        });

    private buildQuery = (...params: KeyValue<any>[]) => {
        const concat = (([key, value]): KeyValue<any>) =>
            `${key}=${value}`;

        const fields = params.map(concat);
        return fields.join('&');
    }
}

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多