File

libs/ngx-pfe/util/i18n-from-state/directive/pfe-i18n-from-state.directive.ts

Description

Interpolates i18n text and data from the state via jsonPath and combines them into an HTMLElement composed of spans (for easy styling).

Takes an i18nFromStateText as input. The value of this key can contain placeholders that look like this.

'I blame %jsonPath%$.variableFromTheState%jsonPath% when my code does not work'

Given that the state contains $.variableFromTheState = 'Jenkins'

The final text will look like: 'I blame Jenkins when my code does not work'

Implements

OnDestroy OnChanges

Metadata

Index

Methods
Inputs

Constructor

constructor(pfeBusinessService: PfeBusinessService, translateService: TranslateService, _renderer: Renderer2, _el: ElementRef, logger: NgxLoggerService)
Parameters :
Name Type Optional
pfeBusinessService PfeBusinessService No
translateService TranslateService No
_renderer Renderer2 No
_el ElementRef No
logger NgxLoggerService No

Inputs

pfeI18nFromState
Type : i18nFromStateText | undefined

Methods

Async renderText
renderText(translatedText: string)

Called by PfeI18nFromStateHandler when the key is changed/translated or when one of the used state values from the expression changes.

Parameters :
Name Type Optional
translatedText string No
Returns : Promise<void>
import { NgxLoggerService } from '@allianz/ngx-logger';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { PfeBusinessService } from '@allianz/ngx-pfe';
import { Directive, ElementRef, Input, OnChanges, OnDestroy, Renderer2, SimpleChanges } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { PfeI18nFromStateHandler, REPLACEMENT_SEPARATOR } from '../pfe-i18n-from-state-handler';

/**
 * Text that can contain placeholders in the form:  %jsonPath%$.variableFromTheState%jsonPath%
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
export type i18nFromStateText = string;

/**
 *
 * Interpolates i18n text and data from the state via jsonPath and combines them into an
 * HTMLElement composed of spans (for easy styling).
 *
 * Takes an i18nFromStateText as input. The value of this key can contain placeholders that look like this.
 *
 * 'I blame %jsonPath%$.variableFromTheState%jsonPath% when my code does not work'
 *
 * Given that the state contains $.variableFromTheState = 'Jenkins'
 *
 * The final text will look like:
 * 'I blame Jenkins when my code does not work'
 *
 * <div [pfeI18nFromState]="I blame %jsonPath%$["app-lang"]%jsonPath% when my code does not work"></div>
 *
 *
 */
@Directive({
  selector: '[pfeI18nFromState]',
})
export class PfeI18nFromStateDirective implements OnDestroy, OnChanges {
  @Input() pfeI18nFromState: i18nFromStateText | undefined;

  private pfeI18nFromStateHandler: PfeI18nFromStateHandler;

  private currentlyRendering = false;

  constructor(
    private pfeBusinessService: PfeBusinessService,
    private translateService: TranslateService,
    private _renderer: Renderer2,
    private _el: ElementRef,
    private logger: NgxLoggerService
  ) {
    this.pfeI18nFromStateHandler = new PfeI18nFromStateHandler(this.pfeBusinessService, this.translateService, this.logger);
    // TODO: Check if a subscription to onTranslationChange, onLangChange and onDefaultLangChange needs to be added here

    // subscribe to onTranslationChange event, in case the translations change
    this.translateService.onTranslationChange.subscribe(() => {
      if (this.pfeI18nFromState) {
        this.pfeI18nFromStateHandler.initializeAndSubscribe(this.pfeI18nFromState, (translatedText: string) =>
          this.renderText(translatedText)
        );
      }
    });

    // subscribe to onLangChange event, in case the language changes
    this.translateService.onLangChange.subscribe(() => {
      if (this.pfeI18nFromState) {
        this.pfeI18nFromStateHandler.initializeAndSubscribe(this.pfeI18nFromState, (translatedText: string) =>
          this.renderText(translatedText)
        );
      }
    });

    // subscribe to onDefaultLangChange event, in case the default language changes
    this.translateService.onDefaultLangChange.subscribe(() => {
      if (this.pfeI18nFromState) {
        this.pfeI18nFromStateHandler.initializeAndSubscribe(this.pfeI18nFromState, (translatedText: string) =>
          this.renderText(translatedText)
        );
      }
    });
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.pfeI18nFromState && this.pfeI18nFromState) {
      this.pfeI18nFromStateHandler.initializeAndSubscribe(this.pfeI18nFromState, (translatedText: string) =>
        this.renderText(translatedText)
      );
    }
  }

  /**
   * Called by PfeI18nFromStateHandler when the key is changed/translated or when one of the used state values from
   * the expression changes.
   */
  async renderText(translatedText: string): Promise<void> {
    // FIXME: Properly fix this!
    if (this.currentlyRendering) {
      return;
    }
    this.currentlyRendering = true;
    const parentHTMLElement: HTMLElement = this._el.nativeElement;

    // Remove whatever it is under the element where this directive is placed
    while (parentHTMLElement.firstChild) {
      parentHTMLElement.removeChild(parentHTMLElement.firstChild);
    }

    /*
    Split the text into chunks delimited by replacementSeparator
    Takes every chunk and translates it again, this is useful for when the values from the
    state are values like 'MONTHLY' or 'legalTermsAccepted'.
    */
    for (const textChunk of translatedText.split(REPLACEMENT_SEPARATOR)) {
      // create a span for every chunk and adds the text and the class.
      const translatedSpan: HTMLSpanElement = this._renderer.createElement('span');
      translatedSpan.className = textChunk.startsWith('$') ? `text-fragment-from-state` : `text-fragment`;
      const finalText = await this.pfeI18nFromStateHandler.getFinalText(textChunk);
      this._renderer.appendChild(translatedSpan, this._renderer.createText(finalText));
      this._renderer.appendChild(parentHTMLElement, translatedSpan);
    }
    this.currentlyRendering = false;
  }

  ngOnDestroy(): void {
    this.pfeI18nFromStateHandler.destroy();
  }
}

results matching ""

    No results matching ""