diff --git a/src/app/param-input/param-input.component.html b/src/app/param-input/param-input.component.html
index b034821a137f2ef616b067b55f424e1eb1bdf390..7aa49591b3f5b36afd7607b0977905dff59dbf5a 100644
--- a/src/app/param-input/param-input.component.html
+++ b/src/app/param-input/param-input.component.html
@@ -1,7 +1,4 @@
 <md-input-container>
-    <input mdInput placeholder="{{_paramDef.symbol}}" [(ngModel)]="_value">
-    <md-hint>{{_hint}}</md-hint>
-</md-input-container>
-<!--
-    <input mdInput placeholder="{{_paramDef.symbol}}" [(ngModel)]="_paramDef.v">
--->
\ No newline at end of file
+    <input mdInput placeholder="{{_paramDef.symbol}}" [ngModel]="_paramDef.v" (ngModelChange)="setValue($event)" />
+    <md-hint>{{_message}}</md-hint>
+</md-input-container>
\ No newline at end of file
diff --git a/src/app/param-input/param-input.component.ts b/src/app/param-input/param-input.component.ts
index 9dbf100f2313da14259c8ab61a61ea8aaf188b6b..ef7041a29d2a8c909b440bd18ea36c58fe02296f 100644
--- a/src/app/param-input/param-input.component.ts
+++ b/src/app/param-input/param-input.component.ts
@@ -1,77 +1,133 @@
-// import { Component, Input, OnInit, DoCheck, OnChanges } from '@angular/core';
-import { Component, Input, OnInit, DoCheck } from '@angular/core';
+// cf. https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
+
+import { Component, Input, forwardRef, OnInit, OnChanges } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl } from '@angular/forms';
 
 import { ParamDefinition } from 'jalhyd';
 
 import { ParamService } from '../param-service/param.service';
 
 @Component({
-    selector: "param-input[symbol]",
+    selector: 'param-input[symbol]',
+    /* OK
+    <input placeholder="{{_paramDef.symbol}}" [ngModel]="_paramDef.v" (ngModelChange)="setValue($event)"/>
+    <p *ngIf="_message">{{_message}}</p>
+    */
     templateUrl: "./param-input.component.html",
+    providers: [
+        {
+            provide: NG_VALUE_ACCESSOR,
+            useExisting: forwardRef(() => ParamInputComponent),
+            multi: true
+        },
+        {
+            provide: NG_VALIDATORS,
+            useExisting: forwardRef(() => ParamInputComponent),
+            multi: true
+        }
+    ]
 })
-// export class ParamInputComponent implements OnInit, DoCheck, OnChanges {
-export class ParamInputComponent implements OnInit, DoCheck {
+export class ParamInputComponent implements ControlValueAccessor, OnInit {
     /**
-    * Parameter symbol (Q, Ks, B, ...) attribute
-    */
-    @Input('symbol') private _paramSymbol: string;
-
-    // private static _idGen: number = 0;
-    // private _id: number;
+      * Parameter symbol (Q, Ks, B, ...) attribute
+      */
+    @Input('symbol')
+    private _paramSymbol: string;
 
     /**
      * managed parameter
      */
     private _paramDef: ParamDefinition;
 
-    /**
-     * currently displayed value
-     */
-    private _value: string;
-
-    /**
-     * hint message
-     */
-    private _hint: string;
+    private _message: string;
 
     constructor(private paramService: ParamService) {
-        // this._id = ParamInputComponent._idGen++;
     }
 
-    ngOnInit(): void {
+    private setValue(event: any) {
+        this.log("ParamInputComponent.setValue");
+        this.log(event);
+        this.validateValue(event);
+    }
+
+    ngOnInit() {
+        this.log("ParamInputComponent.ngOnInit");
+
         // retrieve parameter from symbol
         this._paramDef = this.paramService.getParameter(this._paramSymbol);
-
-        this._value = String(this._paramDef.v);
     }
 
-    ngDoCheck(): void {
-        // let sValue: string = (this._value == undefined) ? "undef" : this._value;
-        // let sParam: string = (this._paramDef.v == undefined) ? "undef" : String(this._paramDef.v);
-        // // console.log("ngDoCheck STA " + this._paramDef.symbol + "(" + this._id + ") old=" + this._old + " value=" + sValue + " param=" + this._paramDef.v);
-        // console.log("ngDoCheck STA " + this._paramDef.symbol + "(" + this._id + ") value=" + sValue + " param=" + sParam);
+    private validateValue(val: any) {
+        this.log("");
 
-        if (this._value == undefined || this._value.trim() == "" || isNaN(+this._value))
-            this._hint = "Please enter a number";
+        let sVal: string;
+
+        let isNum = true;
+        if (val == undefined) {
+            sVal = "undefined";
+            isNum = false;
+        }
         else {
-            this._hint = undefined;
-            let v: number = +this._value;
+            if (typeof val === "string") {
+                isNum = String(val).trim() !== "" && !isNaN(+val)
+                sVal = String(val);
+            }
+        }
+        this.log("ParamInputComponent.validateValue -" + sVal + "-");
+
+        let ok: boolean = true;
+        this._message = undefined;
+        if (!isNum) {
+            ok = false;
+            this._message = "Please enter a numerical value";
+        }
+
+        if (ok) {
+            let nVal = +val;
+
             try {
-                this._paramDef.checkValue(v);  // throws exception if something wrong
-                this._paramDef.v = v;
-                this._value = String(v);
+                this._paramDef.v = nVal;
             }
             catch (e) {
-                this._hint = e;
+                this._message = e;
+                ok = false;
             }
         }
-        // // console.log("ngDoCheck END " + this._paramDef.symbol + "(" + this._id + ") old=" + this._old + " value=" + sValue + " param=" + this._paramDef.v);
-        // let sValue = (this._value == undefined) ? "undef" : this._value;
-        // let sParam = (this._paramDef.v == undefined) ? "undef" : String(this._paramDef.v);
-        // console.log("ngDoCheck END " + this._paramDef.symbol + "(" + this._id + ") value=" + sValue + " param=" + sParam);
+
+
+        if (!ok) {
+            //this._paramDef.undefine();
+            this.log("ParamInputComponent.param " + this._paramDef.toString());
+
+            let err = {
+                rangeError: {
+                    given: val,
+                    max: 4,
+                    min: 0
+                }
+            };
+            return err;
+        }
+
+        this.log("ParamInputComponent.param " + this._paramDef.toString());
+        return null;
+    }
+
+    private log(m: string) {
+        // console.log(m);
+    }
+
+    // ControlValueAccessor interface
+
+    propagateChange = (_: any) => { };
+
+    writeValue(value: any) {
+        this.log("ParamInputComponent.writeValue " + value);
+    }
+
+    registerOnChange(fn: any) {
+        this.propagateChange = fn;
     }
 
-    // ngOnChanges() {
-    //     console.log("ngOnChanges " + this._id);
-    // }
-}
\ No newline at end of file
+    registerOnTouched() { }
+}