Browse Source

fix(admin-ui): Correctly display translatable custom field labels

Michael Bromley 3 years ago
parent
commit
43b776632b

+ 2 - 2
packages/admin-ui/src/lib/core/src/shared/components/custom-field-control/custom-field-control.component.html

@@ -1,12 +1,12 @@
 <div class="clr-form-control" *ngIf="compact">
-    <label for="basic" class="clr-control-label">{{ customField | customFieldLabel }}</label>
+    <label for="basic" class="clr-control-label">{{ customField | customFieldLabel:(uiLanguage$ | async) }}</label>
     <div class="clr-control-container">
         <div class="clr-input-wrapper">
             <ng-container *ngTemplateOutlet="inputs"></ng-container>
         </div>
     </div>
 </div>
-<vdr-form-field [label]="customField | customFieldLabel" [for]="customField.name" *ngIf="!compact">
+<vdr-form-field [label]="customField | customFieldLabel:(uiLanguage$ | async)" [for]="customField.name" *ngIf="!compact">
     <ng-container *ngTemplateOutlet="inputs"></ng-container>
 </vdr-form-field>
 

+ 14 - 12
packages/admin-ui/src/lib/core/src/shared/components/custom-field-control/custom-field-control.component.ts

@@ -1,16 +1,10 @@
-import {
-    AfterViewInit,
-    Component,
-    ComponentFactory,
-    Input,
-    OnInit,
-    ViewChild,
-    ViewContainerRef,
-} from '@angular/core';
-import { FormControl, FormGroup } from '@angular/forms';
+import { Component, ComponentFactory, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
 
 import { InputComponentConfig } from '../../../common/component-registry-types';
-import { CustomFieldConfig, CustomFieldsFragment } from '../../../common/generated-types';
+import { CustomFieldConfig, CustomFieldsFragment, LanguageCode } from '../../../common/generated-types';
 import { DataService } from '../../../data/providers/data.service';
 import {
     CustomFieldComponentService,
@@ -27,7 +21,7 @@ import {
     templateUrl: './custom-field-control.component.html',
     styleUrls: ['./custom-field-control.component.scss'],
 })
-export class CustomFieldControlComponent {
+export class CustomFieldControlComponent implements OnInit {
     @Input() entityName: CustomFieldEntityName;
     @Input('customFieldsFormGroup') formGroup: FormGroup;
     @Input() customField: CustomFieldsFragment;
@@ -37,13 +31,21 @@ export class CustomFieldControlComponent {
     hasCustomControl = false;
     @ViewChild('customComponentPlaceholder', { read: ViewContainerRef })
     private customComponentPlaceholder: ViewContainerRef;
+
     private customComponentFactory: ComponentFactory<CustomFieldControl> | undefined;
+    uiLanguage$: Observable<LanguageCode>;
 
     constructor(
         private dataService: DataService,
         private customFieldComponentService: CustomFieldComponentService,
     ) {}
 
+    ngOnInit() {
+        this.uiLanguage$ = this.dataService.client
+            .uiState()
+            .stream$.pipe(map(({ uiState }) => uiState.language));
+    }
+
     getFieldDefinition(): CustomFieldConfig & { ui?: InputComponentConfig } {
         const config: CustomFieldsFragment & { ui?: InputComponentConfig } = {
             ...this.customField,

+ 2 - 2
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/select-form-input/select-form-input.component.html

@@ -1,6 +1,6 @@
 <select clrSelect [formControl]="formControl" [vdrDisabled]="readonly">
     <option *ngIf="config.nullable" [ngValue]="null"></option>
-    <option *ngFor="let option of options" [ngValue]="option.value">
-        {{ (option | customFieldLabel) || option.label || option.value }}
+    <option *ngFor="let option of options;trackBy:trackByFn" [ngValue]="option.value">
+        {{ (option | customFieldLabel:(uiLanguage$ | async)) || option.label || option.value }}
     </option>
 </select>

+ 17 - 4
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/select-form-input/select-form-input.component.ts

@@ -1,9 +1,11 @@
-import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
+import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
 import { FormControl } from '@angular/forms';
 import { DefaultFormComponentConfig, DefaultFormComponentId } from '@vendure/common/lib/shared-types';
+import { Observable } from 'rxjs';
 
-import { FormInputComponent, InputComponentConfig } from '../../../common/component-registry-types';
-import { CustomFieldConfigFragment } from '../../../common/generated-types';
+import { FormInputComponent } from '../../../common/component-registry-types';
+import { CustomFieldConfigFragment, LanguageCode } from '../../../common/generated-types';
+import { DataService } from '../../../data/providers/data.service';
 
 /**
  * @description
@@ -19,13 +21,24 @@ import { CustomFieldConfigFragment } from '../../../common/generated-types';
     styleUrls: ['./select-form-input.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
-export class SelectFormInputComponent implements FormInputComponent {
+export class SelectFormInputComponent implements FormInputComponent, OnInit {
     static readonly id: DefaultFormComponentId = 'select-form-input';
     @Input() readonly: boolean;
     formControl: FormControl;
     config: DefaultFormComponentConfig<'select-form-input'> & CustomFieldConfigFragment;
+    uiLanguage$: Observable<LanguageCode>;
 
     get options() {
         return this.config.ui?.options || this.config.options;
     }
+
+    constructor(private dataService: DataService) {}
+
+    ngOnInit() {
+        this.uiLanguage$ = this.dataService.client.uiState().mapStream(({ uiState }) => uiState.language);
+    }
+
+    trackByFn(index: number, item: any) {
+        return item.value;
+    }
 }

+ 5 - 22
packages/admin-ui/src/lib/core/src/shared/pipes/custom-field-label.pipe.ts

@@ -1,8 +1,6 @@
-import { OnDestroy, Pipe, PipeTransform } from '@angular/core';
-import { Subscription } from 'rxjs';
+import { Pipe, PipeTransform } from '@angular/core';
 
 import { CustomFieldConfig, LanguageCode, StringFieldOption } from '../../common/generated-types';
-import { DataService } from '../../data/providers/data.service';
 
 /**
  * Displays a localized label for a CustomField or StringFieldOption, falling back to the
@@ -10,38 +8,23 @@ import { DataService } from '../../data/providers/data.service';
  */
 @Pipe({
     name: 'customFieldLabel',
-    pure: false,
+    pure: true,
 })
-export class CustomFieldLabelPipe implements PipeTransform, OnDestroy {
-    private readonly subscription: Subscription;
-    private uiLanguageCode: LanguageCode;
-
-    constructor(private dataService: DataService) {
-        this.subscription = dataService.client.uiState().stream$.subscribe(val => {
-            this.uiLanguageCode = val.uiState.language;
-        });
-    }
-
-    transform(value: CustomFieldConfig | StringFieldOption): string {
+export class CustomFieldLabelPipe implements PipeTransform {
+    transform(value: CustomFieldConfig | StringFieldOption, uiLanguageCode: LanguageCode | null): string {
         if (!value) {
             return value;
         }
         const { label } = value;
         const name = this.isCustomFieldConfig(value) ? value.name : value.value;
         if (label) {
-            const match = label.find(l => l.languageCode === this.uiLanguageCode);
+            const match = label.find(l => l.languageCode === uiLanguageCode);
             return match ? match.value : label[0].value;
         } else {
             return name;
         }
     }
 
-    ngOnDestroy(): void {
-        if (this.subscription) {
-            this.subscription.unsubscribe();
-        }
-    }
-
     private isCustomFieldConfig(input: any): input is CustomFieldConfig {
         return input.hasOwnProperty('name');
     }