javascript - KeyValue 和 AutoComplete 的 Angular Filter Pipe

标签 javascript angular typescript angular-pipe

首先,我想用这个管道显示国家并用插入的字符过滤它们,我需要 ISO 代码来显示国家的旗帜。问题是我想使用一个库,其中包含所有国家/地区的 ISO 代码和内容。这具有键值形式。

首先,我将这些数据导出到 var 以便能够使用这些数据。

export var indexedArray: { [key: string]: string } 
countryStuff: Country; //currently not used

countries = [] as Array<string>
filteredCountries: Observable<string[]>;

export interface Country { //currently not used
  [key: string]: string
}

ngOnInit() {
 this.startDate.setFullYear(this.startDate.getFullYear() - 18);
 this.buildForm();

 this.filteredCountries = this.personalForm.controls['country'].valueChanges
   .pipe(
     startWith(''),
     map(value => this._filter(value))
   );

 i18nIsoCountries.registerLocale(require("i18n-iso-countries/langs/en.json"));
 i18nIsoCountries.registerLocale(require("i18n-iso-countries/langs/de.json"));

 this.currentLanguage = this.translateService.currentLang;

 indexedArray = i18nIsoCountries.getNames(this.currentLanguage);
 for (let key in indexedArray) {
   let value = indexedArray[key];
   this.countries.push(value);
 }
}

在 html 中我可以这样使用:

  <mat-option *ngFor="let item of countryStuff | keyvalue:keepOriginalOrder" [value]="item.key">
     Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
  </mat-option>

我也可以使用常规方式,但完全没有键值方式,就像 Angular 示例所说的那样(没有 TS 逻辑):

 <mat-option *ngFor="let option of filteredCountries | async" [value]="option">
    <span class="flag-icon flag-icon-de flag-icon-squared"></span>
    {{option}}
 </mat-option>

这只是给了我完整的国家/地区名称,例如 Algolia 之类的。

我在这里找到了一个想法https://long2know.com/2017/04/angular-pipes-filtering-on-multiple-keys/但我不能为了我的目的改变它。如果我可以针对 keyvalue 进行过滤,那就更完美了,所以也许“DE”代表德国的关键,“Ger”代表德国的值(value)。现有管道似乎不可能。

根据要求编辑(过滤):

private _filter(value: string): string[] {
 var filterValue;
 if (value) {
   filterValue = value.toLowerCase();
 } else {
   filterValue = "";
 }
 return this.countries.filter(option => option.toLowerCase().startsWith(filterValue));
}

还更新了 ngOnInit()

最佳答案

我用 i18n 库甚至 flag-icon-css

让它工作

TypeScript(过滤器类):

@Pipe({
  name: 'filterLanguages'
})
export class FilterLanguages implements PipeTransform {
  transform(items: any, filter: any, isAnd: boolean): any {
    if (filter && Array.isArray(items)) {
      let filterKeys = Object.keys(filter);
      if (isAnd) {
        return items.filter(item =>
          filterKeys.reduce((memo, keyName) =>
            (memo && new RegExp(filter[keyName], 'gi').test(item[keyName])) || filter[keyName] === "", true));
      } else {
        return items.filter(item => {
          return filterKeys.some((keyName) => {
            return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] === "";
          });
        });
      }
    } else {
      return items;
    }
  }
}

HTML:

<mat-form-field class="field-sizing">
  <input matInput required placeholder="{{ 'REGISTRATION.COUNTRY' | translate }}" name="country"
    id="country" [matAutocomplete]="auto" formControlName="country" [value]="filterText" />
  <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
    <mat-option *ngFor="let item of countries | filterLanguages:{ name: filterText, iso: filterText, flagId: filterText } : false" [value]="item.name">
      <span class="flag-icon flag-icon-{{item.flagId}} flag-icon-squared"></span>
      {{ item.name }} - {{ item.iso }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

typescript (组件):

export var countryList: {
  [key: string]: string
}

declare const require;

export class YourComponent implements OnInit {

  countries = [] as Array<any>
  currentLanguage: string;
  filterText: string;

  ngOnInit() {
    i18nIsoCountries.registerLocale(require("i18n-iso-countries/langs/en.json"));
    i18nIsoCountries.registerLocale(require("i18n-iso-countries/langs/de.json"));

    this.currentLanguage = this.translateService.currentLang;
    countryList = i18nIsoCountries.getNames(this.currentLanguage);

    this.buildForm();
    this.createCountries();

    this.personalForm.controls['country']
      .valueChanges
      .pipe(debounceTime(100))
      .pipe(distinctUntilChanged())
      .subscribe(term => {
        this.filterText = term;
      });
  }

  ngAfterContentChecked() {
    this.cdRef.detectChanges();

    if (this.currentLanguage != this.translateService.currentLang) {
      countryList = i18nIsoCountries.getNames(this.translateService.currentLang);

      this.createCountries();

      this.currentLanguage = this.translateService.currentLang;
      this.personalForm.get('country').updateValueAndValidity();
    }
  }

  createCountries() {
    this.countries = [];
    for (let key in countryList) {
      var countryName: string = countryList[key];
      var isoValue: string = key;
      var isoLowerValue: string = key.toLowerCase();

      this.countries.push({ name: countryName, iso: isoValue, flagId: isoLowerValue })
    }
  }

您需要 i18n 库,例如我的示例中的 formControl。

关于javascript - KeyValue 和 AutoComplete 的 Angular Filter Pipe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56535386/

相关文章:

c# - 使用 Javascript 删除 GridviewRow?

javascript - 为什么 JS 不滚动到顶部?

javascript - 无法根据条件更改输入背景

javascript - 将参数传递给 jQuery 函数

javascript - 在不损害页面响应能力的情况下设置 col-md-* div 类之间的边距

javascript - 可观察中的数据集未在模板中更新

angularjs - Angular NgUpgrade 将 AngularJS 服务注入(inject) Angular 服务;获取 : Unhandled Promise rejection: Cannot read property 'get' of undefined ; Zone:

javascript - 过滤掉 typescript 中接口(interface)不需要的对象属性

typescript 模板文字类型强制结构

reactjs - 由于 CORS 错误,POST 请求在 react axios 中被阻止