简体   繁体   English

KeyValue和AutoComplete的角度过滤管道

[英]Angular Filter Pipe for KeyValue and AutoComplete

First of all I want to show countries with this pipe and filter them with inserted characters and I need the ISO codes to show the flags of the countries. 首先,我想显示具有此管道的国家并使用插入的字符过滤它们,我需要ISO代码来显示国家/地区的标志。 The problem is that I want to use a library which has all countries with ISO codes and stuff. 问题是我想使用一个拥有ISO代码和东西的所有国家的图书馆。 This has the key value form. 这具有关键值形式。

First of all I export this data to var to be able to use the data. 首先,我将此数据导出到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);
 }
}

In the html I can use this like this: 在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>

The normal way I can also use but completly without the key value way and just like the Angular examples say (without the TS logic): 正常的方式我也可以使用但不完全没有键值方式,就像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>

That just gives me the full country name like Algeria or something. 这只是给我一个完整的国家名称,如阿尔及利亚或其他什么。

I have found an idea here https://long2know.com/2017/04/angular-pipes-filtering-on-multiple-keys/ but I couldn't change it for my purposes. 我在这里找到了一个想法https://long2know.com/2017/04/angular-pipes-filtering-on-multiple-keys/但是我不能为了我的目的而改变它。 That would be even more perfect if I could filter for key and value so maybe "DE" for key and "Ger" for value of Germany. 如果我可以过滤关键价值 ,那将更加完美,因此可能“DE”代表关键,“Ger”代表德国价值。 It does not seem to be possible with existing pipes. 现有管道似乎不可能。

Edit on request (filtering): 根据要求编辑(过滤):

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

Also updated the ngOnInit() 还更新了ngOnInit()

I got it working with the i18n library and even flag-icon-css 我使用了i18n库甚至是flag-icon-css

TypeScript (filter class): 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: 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 (component): 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 })
    }
  }

You need the i18n library and like in my example a formControl. 你需要i18​​n库,在我的例子中就像formControl一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM