From 4393233611f2a54c63426e878c93114b5d2d42ef Mon Sep 17 00:00:00 2001
From: Carlo Nomes <carlo.nomes@optis.be>
Date: Fri, 1 Feb 2019 14:04:47 +0100
Subject: [PATCH] feat(stark-ui): add directive for transforming input value
 before passing it to a ngControl

  - added directive `[starkTransformInput]`
  - added partial demo
  - small refactor demo page
  - added test for directive

ISSUES CLOSED: #1099
---
 .../modules/keyboard-directives/directives.ts |   1 +
 .../transform-input.directive.spec.ts         |  51 ++++++++
 .../directives/transform-input.directive.ts   |  93 +++++++++++++++
 .../keyboard-directives.module.ts             |   6 +-
 showcase/src/app/demo-ui/demo-ui.module.ts    |   3 +-
 ...mo-keyboard-directives-page.component.html | 110 ++++++++++--------
 ...mo-keyboard-directives-page.component.scss |  10 --
 ...demo-keyboard-directives-page.component.ts |   9 +-
 showcase/src/assets/translations/en.json      |   5 +
 showcase/src/assets/translations/fr.json      |   5 +
 showcase/src/assets/translations/nl.json      |   5 +
 11 files changed, 236 insertions(+), 62 deletions(-)
 create mode 100644 packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.spec.ts
 create mode 100644 packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.ts

diff --git a/packages/stark-ui/src/modules/keyboard-directives/directives.ts b/packages/stark-ui/src/modules/keyboard-directives/directives.ts
index 3cbc7b907c..05c3f63118 100644
--- a/packages/stark-ui/src/modules/keyboard-directives/directives.ts
+++ b/packages/stark-ui/src/modules/keyboard-directives/directives.ts
@@ -1,2 +1,3 @@
 export * from "./directives/on-enter-key.directive";
 export * from "./directives/restrict-input.directive";
+export * from "./directives/transform-input.directive";
diff --git a/packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.spec.ts b/packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.spec.ts
new file mode 100644
index 0000000000..98e20e5adc
--- /dev/null
+++ b/packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.spec.ts
@@ -0,0 +1,51 @@
+import { Component, DebugElement } from "@angular/core";
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
+import { By } from "@angular/platform-browser";
+import { StarkTransformInputDirective } from "@nationalbankbelgium/stark-ui";
+import { MockStarkLoggingService } from "@nationalbankbelgium/stark-core/testing";
+import { STARK_LOGGING_SERVICE } from "@nationalbankbelgium/stark-core";
+
+fdescribe("TransformsInputDirective with ngModel", () => {
+	@Component({
+		selector: "test-component",
+		template: "<input [(ngModel)]='value' [starkTransformInput]='transformation'/>"
+	})
+	class TestComponent {
+		public value: string = "";
+		public transformation = (value: string) => value.toUpperCase();
+	}
+
+	let fixture: ComponentFixture<TestComponent>;
+
+	beforeEach(() => {
+		TestBed.configureTestingModule({
+			declarations: [StarkTransformInputDirective, TestComponent],
+			imports: [
+				FormsModule,
+				ReactiveFormsModule
+			],
+			providers: [
+				{ provide: STARK_LOGGING_SERVICE, useValue: new MockStarkLoggingService() }
+			]
+		});
+
+		fixture = TestBed.createComponent(TestComponent);
+		// trigger initial data binding
+		fixture.detectChanges();
+	});
+
+	it("should set the value to uppercase", () => {
+		expect(fixture.componentInstance.value).toBe("", "Field 'value' should start as empty string ");
+
+		// Mock input event
+		const debugInputElement: DebugElement = fixture.debugElement.query(By.css("input"));
+		const inputElement: HTMLInputElement = (<HTMLInputElement>debugInputElement.nativeElement);
+		inputElement.value = "a";
+		inputElement.dispatchEvent(new Event("input"));
+		fixture.detectChanges();
+
+		expect(fixture.componentInstance.value).toBe("A", "Field 'value' should have been updated to upper case 'A'");
+	});
+
+});
diff --git a/packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.ts b/packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.ts
new file mode 100644
index 0000000000..cb9bff413f
--- /dev/null
+++ b/packages/stark-ui/src/modules/keyboard-directives/directives/transform-input.directive.ts
@@ -0,0 +1,93 @@
+import { Directive, ElementRef, forwardRef, Input, Renderer2 } from "@angular/core";
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
+
+export const STARK_TRANSFORM_INPUT_PROVIDER: any = {
+	provide: NG_VALUE_ACCESSOR,
+	// tslint:disable-next-line:no-forward-ref
+	useExisting: forwardRef(() => StarkTransformInputDirective),
+	multi: true
+};
+
+/**
+ * Directive to transform the value of an input / textarea before it is passed on to the ngControl (ngModel, formControl).
+ * This is mostly based on {@link: @angular/forms/DefaultValueAccessor}
+ */
+@Directive({
+	// tslint:disable-next-line:directive-selector
+	selector: "[starkTransformInput]",
+	providers: [STARK_TRANSFORM_INPUT_PROVIDER],
+	host: {
+		"(input)": "$any(this)._handleInput($event.target.value)",
+		"(blur)": "onTouched()"
+	}
+})
+export class StarkTransformInputDirective implements ControlValueAccessor {
+	// tslint:disable-next-line:no-input-rename
+	@Input("starkTransformInput")
+	public transformFunction: (value: any) => any;
+
+	/**
+	 * The registered callback function called when an input event occurs on the input element.
+	 */
+	public onChange = (_: any) => {/*noop*/};
+
+	/**
+	 * The registered callback function called when a blur event occurs on the input element.
+	 */
+	public onTouched = () => {/*noop*/};
+
+	/**
+	 * Class constructor
+	 * @param logger - The logger of the application
+	 * @param _renderer - Angular renderer
+	 * @param _elementRef - Reference to the element
+	 */
+	public constructor(private _renderer: Renderer2,
+										 private _elementRef: ElementRef) {
+	}
+
+	/**
+	 * Sets the "value" property on the input element.
+	 *
+	 * @param value The checked value
+	 */
+	public writeValue(value: any): void {
+		const normalizedValue: any = value === null ? "" : value;
+		this._renderer.setProperty(this._elementRef.nativeElement, "value", normalizedValue);
+	}
+
+	/**
+	 * Registers a function called when the control value changes.
+	 *
+	 * @param fn The callback function
+	 */
+	public registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
+
+	/**
+	 * Registers a function called when the control is touched.
+	 *
+	 * @param fn The callback function
+	 */
+	public registerOnTouched(fn: () => void): void { this.onTouched = fn; }
+
+	/**
+	 * Sets the "disabled" property on the input element.
+	 *
+	 * @param isDisabled The disabled value
+	 */
+	public setDisabledState(isDisabled: boolean): void {
+		this._renderer.setProperty(this._elementRef.nativeElement, "disabled", isDisabled);
+	}
+
+	/** @internal */
+	public _handleInput(value: any): void {
+		const transformed: any = this.transformFunction(value);
+		if (transformed !== value) {
+			this._elementRef.nativeElement.value = transformed;
+			this.onChange(transformed);
+		} else {
+			this.onChange(value);
+		}
+	}
+
+}
diff --git a/packages/stark-ui/src/modules/keyboard-directives/keyboard-directives.module.ts b/packages/stark-ui/src/modules/keyboard-directives/keyboard-directives.module.ts
index 007412c877..b7c7511a92 100644
--- a/packages/stark-ui/src/modules/keyboard-directives/keyboard-directives.module.ts
+++ b/packages/stark-ui/src/modules/keyboard-directives/keyboard-directives.module.ts
@@ -1,8 +1,8 @@
 import { NgModule } from "@angular/core";
-import { StarkOnEnterKeyDirective, StarkRestrictInputDirective } from "./directives";
+import { StarkTransformInputDirective, StarkOnEnterKeyDirective, StarkRestrictInputDirective } from "./directives";
 
 @NgModule({
-	declarations: [StarkOnEnterKeyDirective, StarkRestrictInputDirective],
-	exports: [StarkOnEnterKeyDirective, StarkRestrictInputDirective]
+	declarations: [StarkOnEnterKeyDirective, StarkRestrictInputDirective, StarkTransformInputDirective],
+	exports: [StarkOnEnterKeyDirective, StarkRestrictInputDirective, StarkTransformInputDirective]
 })
 export class StarkKeyboardDirectivesModule {}
diff --git a/showcase/src/app/demo-ui/demo-ui.module.ts b/showcase/src/app/demo-ui/demo-ui.module.ts
index 27ca15a9e9..058451dd68 100644
--- a/showcase/src/app/demo-ui/demo-ui.module.ts
+++ b/showcase/src/app/demo-ui/demo-ui.module.ts
@@ -1,6 +1,6 @@
 import { NgModule } from "@angular/core";
 import { CommonModule } from "@angular/common";
-import { FormsModule } from "@angular/forms";
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
 import { MAT_DATE_FORMATS } from "@angular/material/core";
 import { MatCheckboxModule } from "@angular/material/checkbox";
 import { MatButtonModule } from "@angular/material/button";
@@ -77,6 +77,7 @@ import {
 		}),
 		CommonModule,
 		FormsModule,
+		ReactiveFormsModule,
 		MatButtonModule,
 		MatButtonToggleModule,
 		MatCardModule,
diff --git a/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.html b/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.html
index f30a8ac282..c646ba5840 100644
--- a/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.html
+++ b/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.html
@@ -2,43 +2,44 @@ <h1 class="mat-display-3" translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.TITLE</h1>
 <section class="stark-section">
 	<h1 translate>SHOWCASE.DEMO.SHARED.EXAMPLE_VIEWER_LIST</h1>
 	<example-viewer
-		[extensions]="['HTML', 'TS']"
-		filesPath="keyboard-directives/on-enter-key-directive"
-		exampleTitle="SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TITLE"
+			[extensions]="['HTML', 'TS']"
+			filesPath="keyboard-directives/on-enter-key-directive"
+			exampleTitle="SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TITLE"
 	>
-		<form class="on-enter-key-directive-form">
+		<form  fxLayout="column">
 			<p translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.DESCRIPTION</p>
 			<mat-form-field>
 				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.INPUT_WITH_CONTEXT</mat-label>
 				<input
-					name="test"
-					[(ngModel)]="inputValue1"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TYPE_AND_PRESS_ENTER' | translate }}"
-					[starkOnEnterKey]="onEnterKeyCallback.bind(this)"
-					[starkOnEnterKeyParams]="['input1', inputValue1, 123, { prop: 'someValue' }]"
+						name="test"
+						[(ngModel)]="inputValue1"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TYPE_AND_PRESS_ENTER' | translate }}"
+						[starkOnEnterKey]="onEnterKeyCallback.bind(this)"
+						[starkOnEnterKeyParams]="['input1', inputValue1, 123, { prop: 'someValue' }]"
 				/>
 			</mat-form-field>
 			<mat-form-field>
 				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.INPUT_WITHOUT_CONTEXT</mat-label>
 				<input
-					name="test"
-					[(ngModel)]="inputValue2"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TYPE_PRESS_ENTER_AND_CHECK_CONSOLE' | translate }}"
-					[starkOnEnterKey]="onEnterKeyCallback"
-					[starkOnEnterKeyParams]="['input2', inputValue2, 123, { prop: 'someValue' }]"
+						name="test"
+						[(ngModel)]="inputValue2"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TYPE_PRESS_ENTER_AND_CHECK_CONSOLE' | translate }}"
+						[starkOnEnterKey]="onEnterKeyCallback"
+						[starkOnEnterKeyParams]="['input2', inputValue2, 123, { prop: 'someValue' }]"
 				/>
 			</mat-form-field>
 			<mat-form-field>
-				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.INPUT_WITHOUT_CONTEXT_ALTERNATIVE </mat-label>
+				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.INPUT_WITHOUT_CONTEXT_ALTERNATIVE
+				</mat-label>
 				<input
-					name="test"
-					[(ngModel)]="inputValue3"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TYPE_AND_PRESS_ENTER' | translate }}"
-					[starkOnEnterKey]="onEnterKeyCallback"
-					[starkOnEnterKeyParams]="['input3', inputValue3, 123, { prop: 'someValue' }, this]"
+						name="test"
+						[(ngModel)]="inputValue3"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.ON_ENTER_KEY.TYPE_AND_PRESS_ENTER' | translate }}"
+						[starkOnEnterKey]="onEnterKeyCallback"
+						[starkOnEnterKeyParams]="['input3', inputValue3, 123, { prop: 'someValue' }, this]"
 				/>
 			</mat-form-field>
 		</form>
@@ -47,49 +48,66 @@ <h1 translate>SHOWCASE.DEMO.SHARED.EXAMPLE_VIEWER_LIST</h1>
 	</example-viewer>
 
 	<example-viewer
-		[extensions]="['HTML', 'TS']"
-		filesPath="keyboard-directives/restrict-input-directive"
-		exampleTitle="SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TITLE"
+			[extensions]="['HTML', 'TS']"
+			filesPath="keyboard-directives/restrict-input-directive"
+			exampleTitle="SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TITLE"
 	>
-		<form class="restrict-input-directive-form">
+		<form fxLayout="column">
 			<p translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.DESCRIPTION</p>
 			<mat-form-field>
 				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_ONLY_NUMBERS</mat-label>
 				<input
-					name="test"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
-					starkRestrictInput="\d"
+						name="test"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
+						starkRestrictInput="\d"
 				/>
 			</mat-form-field>
 			<mat-form-field>
-				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_ALPHANUMERICAL_CHARACTERS </mat-label>
+				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_ALPHANUMERICAL_CHARACTERS
+				</mat-label>
 				<input
-					name="test"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
-					starkRestrictInput="^[A-Za-z0-9]*$"
+						name="test"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
+						starkRestrictInput="^[A-Za-z0-9]*$"
 				/>
 			</mat-form-field>
 			<mat-form-field>
-				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_NO_SPECIAL_CHARACTERS </mat-label>
+				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_NO_SPECIAL_CHARACTERS
+				</mat-label>
 				<input
-					name="test"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
-					starkRestrictInput="\w"
+						name="test"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
+						starkRestrictInput="\w"
 				/>
 			</mat-form-field>
 			<mat-form-field>
-				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_UPPERCASE_CHARACTERS</mat-label>
+				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.INPUT_UPPERCASE_CHARACTERS
+				</mat-label>
 				<input
-					name="test"
-					matInput
-					placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
-					starkRestrictInput="^[A-Z]*$"
+						name="test"
+						matInput
+						placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.RESTRICT_INPUT.TYPE_A_VALUE' | translate }}"
+						starkRestrictInput="^[A-Z]*$"
 				/>
 			</mat-form-field>
 		</form>
 	</example-viewer>
+
+	<example-viewer [extensions]="['HTML', 'TS']"
+					filesPath="keyboard-directives/restrict-input-directive"
+					exampleTitle="SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.TRANSFORM_INPUT.TITLE">
+		<div fxlayout="column">
+			<mat-form-field fxFlex>
+				<mat-label translate>SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.TRANSFORM_INPUT.ONLY_UPPER_CASE_LABEL</mat-label>
+				<input matInput
+					   placeholder="{{ 'SHOWCASE.DEMO.KEYBOARD_DIRECTIVES.TRANSFORM_INPUT.ONLY_UPPER_CASE_PLACEHOLDER' | translate }}"
+					   [formControl]="transformFormControl"
+					   [starkTransformInput]="transformFunction"/>
+			</mat-form-field>
+		</div>
+	</example-viewer>
 </section>
 <stark-reference-block [links]="referenceList"></stark-reference-block>
diff --git a/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.scss b/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.scss
index 9bed527bce..4035ed81d1 100644
--- a/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.scss
+++ b/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.scss
@@ -1,13 +1,3 @@
-.on-enter-key-directive-form {
-  display: flex;
-  flex-direction: column;
-}
-
-.restrict-input-directive-form {
-  display: flex;
-  flex-direction: column;
-}
-
 pre code {
   display: block;
   height: 200px;
diff --git a/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.ts b/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.ts
index 5752803add..79f95eca6d 100644
--- a/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.ts
+++ b/showcase/src/app/demo-ui/pages/keyboard-directives/demo-keyboard-directives-page.component.ts
@@ -1,6 +1,7 @@
 import { Component, Inject, OnInit } from "@angular/core";
 import { STARK_LOGGING_SERVICE, StarkLoggingService } from "@nationalbankbelgium/stark-core";
 import { ReferenceLink } from "../../../shared/components";
+import { FormControl } from "@angular/forms";
 
 @Component({
 	selector: "demo-keyboard-directives",
@@ -12,12 +13,14 @@ export class DemoKeyboardDirectivesPageComponent implements OnInit {
 	public inputValue1: string;
 	public inputValue2: string;
 	public inputValue3: string;
-
+	public transformFormControl: FormControl = new FormControl("", [], []);
 	public logging: string;
 
 	public referenceList: ReferenceLink[];
+	public transformFunction = (value: string): string => value.toUpperCase();
 
-	public constructor(@Inject(STARK_LOGGING_SERVICE) private logger: StarkLoggingService) {}
+	public constructor(@Inject(STARK_LOGGING_SERVICE) private logger: StarkLoggingService) {
+	}
 
 	/**
 	 * Component lifecycle hook
@@ -39,6 +42,8 @@ export class DemoKeyboardDirectivesPageComponent implements OnInit {
 				url: "https://stark.nbb.be/api-docs/stark-ui/latest/directives/StarkRestrictInputDirective.html"
 			}
 		];
+
+		this.transformFormControl.valueChanges.subscribe((v: string) => this.logger.debug("transformFormControl value changed: ", v));
 	}
 
 	public onEnterKeyCallback(...paramValues: any[]): void {
diff --git a/showcase/src/assets/translations/en.json b/showcase/src/assets/translations/en.json
index a78b891230..bd77df7e4f 100644
--- a/showcase/src/assets/translations/en.json
+++ b/showcase/src/assets/translations/en.json
@@ -101,6 +101,11 @@
           "INPUT_UPPERCASE_CHARACTERS": "Accept only uppercase characters",
           "TYPE_A_VALUE": "Type a value"
         },
+        "TRANSFORM_INPUT": {
+          "TITLE": "Transform Input Directive",
+          "ONLY_UPPER_CASE_LABEL": "Upper case input",
+          "ONLY_UPPER_CASE_PLACEHOLDER": "ONLY UPPER CASE"
+        },
         "TITLE": "Keyboard directive"
       },
       "LANGUAGE_SELECTOR": {
diff --git a/showcase/src/assets/translations/fr.json b/showcase/src/assets/translations/fr.json
index a319036271..2b224e8d3e 100644
--- a/showcase/src/assets/translations/fr.json
+++ b/showcase/src/assets/translations/fr.json
@@ -101,6 +101,11 @@
           "INPUT_UPPERCASE_CHARACTERS": "Accepter uniquement les majuscules",
           "TYPE_A_VALUE": "Taper une valeur"
         },
+        "TRANSFORM_INPUT": {
+          "TITLE": "Transform Input Directive",
+          "ONLY_UPPER_CASE_LABEL": "Upper case input",
+          "ONLY_UPPER_CASE_PLACEHOLDER": "ONLY UPPER CASE"
+        },
         "TITLE": "Keyboard directive"
       },
       "LANGUAGE_SELECTOR": {
diff --git a/showcase/src/assets/translations/nl.json b/showcase/src/assets/translations/nl.json
index 0fd7abffd1..52b65bff28 100644
--- a/showcase/src/assets/translations/nl.json
+++ b/showcase/src/assets/translations/nl.json
@@ -101,6 +101,11 @@
           "INPUT_UPPERCASE_CHARACTERS": "Aanvaard enkel hoofdletters",
           "TYPE_A_VALUE": "Geef een waarde in"
         },
+        "TRANSFORM_INPUT": {
+          "TITLE": "Transform Input Directive",
+          "ONLY_UPPER_CASE_LABEL": "Upper case input",
+          "ONLY_UPPER_CASE_PLACEHOLDER": "ONLY UPPER CASE"
+        },
         "TITLE": "Keyboard directive"
       },
       "LANGUAGE_SELECTOR": {