diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 8a85a687608f5db8ba20e0fa4d41147cb147488b..8e8a97224e930705389f84cb9989de7326bfce74 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -7,6 +7,7 @@ import { ParamService } from './param-service/param.service';
   template: `
   <h1>{{title}}</h1>
   <param-input symbol="Q"></param-input>
+  <param-input symbol="Q"></param-input>
   <param-input symbol="Ks"></param-input>
   <!--
   -->
diff --git a/src/app/param-input/param-input.component.html b/src/app/param-input/param-input.component.html
index 7aa49591b3f5b36afd7607b0977905dff59dbf5a..265cb5a83cdde77da15e7abfc7aab17d41e939d5 100644
--- a/src/app/param-input/param-input.component.html
+++ b/src/app/param-input/param-input.component.html
@@ -1,4 +1,13 @@
 <md-input-container>
-    <input mdInput placeholder="{{_paramDef.symbol}}" [ngModel]="_paramDef.v" (ngModelChange)="setValue($event)" />
+    <input mdInput placeholder="{{_paramDef.symbol}}" [ngModel]="_uiValue.uncheckValueString" (ngModelChange)="setValue($event)"
+    />
     <md-hint>{{_message}}</md-hint>
-</md-input-container>
\ No newline at end of file
+</md-input-container>
+<!--
+    <md-error *ngIf="_message">
+        {{_message}}
+    </md-error>
+    <input mdInput placeholder="{{_paramDef.symbol}}" [ngModel]="getValue()" (ngModelChange)="setValue($event)" />
+    <md-error *ngIf="hasError()">
+    <md-hint *ngIf="hasError()">{{_message}}</md-hint>
+-->
\ 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 ef7041a29d2a8c909b440bd18ea36c58fe02296f..ead9e02853cb0ef173c38409834ec0248cbd2dc3 100644
--- a/src/app/param-input/param-input.component.ts
+++ b/src/app/param-input/param-input.component.ts
@@ -1,9 +1,9 @@
 // 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 { Component, Input, forwardRef, OnInit, DoCheck, ChangeDetectorRef } from '@angular/core';
 import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl } from '@angular/forms';
 
-import { ParamDefinition } from 'jalhyd';
+import { ParamDefinition, NumericalString } from 'jalhyd';
 
 import { ParamService } from '../param-service/param.service';
 
@@ -27,7 +27,7 @@ import { ParamService } from '../param-service/param.service';
         }
     ]
 })
-export class ParamInputComponent implements ControlValueAccessor, OnInit {
+export class ParamInputComponent implements ControlValueAccessor, OnInit, DoCheck {
     /**
       * Parameter symbol (Q, Ks, B, ...) attribute
       */
@@ -41,67 +41,144 @@ export class ParamInputComponent implements ControlValueAccessor, OnInit {
 
     private _message: string;
 
-    constructor(private paramService: ParamService) {
+    private static _idGen: number = 0; // A VIRER
+    private _id: number; // A VIRER
+    private static _startTime: number;  // A VIRER
+
+    /**
+     * true si la modification du paramètre géré vient de l'interface utilisateur
+     *
+     * false si la modification du paramètre géré vient d'un appel du code
+     */
+    private _fromUI: boolean;
+
+    /**
+     * valeur dans le contrôle (saisie par l'utilisateur)
+     */
+    // private _uiValue: string;
+    private _uiValue: NumericalString;
+
+    constructor(private paramService: ParamService, private changeDetector: ChangeDetectorRef) {
+        this._id = ParamInputComponent._idGen++;
+        if (ParamInputComponent._startTime == undefined)
+            ParamInputComponent._startTime = new Date().getTime();
+
+        this._uiValue = new NumericalString();
     }
 
-    private setValue(event: any) {
-        this.log("ParamInputComponent.setValue");
-        this.log(event);
-        this.validateValue(event);
+    hasError(): boolean {
+        let res = (this._message != undefined);
+        if (res)
+            this.log("hasError : true " + this._message);
+        else
+            this.log("hasError : false");
+        return res;
     }
 
-    ngOnInit() {
-        this.log("ParamInputComponent.ngOnInit");
+    private getSfromUI(): string {
+        return this._fromUI ? " fromUI " : " fromMODEL";
+    }
+
+    private getSParam(): string {
+        return " " + this._paramDef.symbol + "=" + this._paramDef.toString()
+    }
 
+    private getSUIvalue(v: NumericalString = undefined): string {
+        if (v == undefined)
+            return "  uiValue=" + this._uiValue.toString() + "";
+
+        return "  uiValue=" + v.toString() + "";
+    }
+
+    ngOnInit() {
         // retrieve parameter from symbol
         this._paramDef = this.paramService.getParameter(this._paramSymbol);
     }
 
-    private validateValue(val: any) {
-        this.log("");
+    // private getValue() {
+    //     if (this._paramDef.isDefined)
+    //         return this._paramDef.v;
+    //     return "";
 
-        let sVal: string;
+    //     // return this._uiValue.value;
+    // }
 
-        let isNum = true;
-        if (val == undefined) {
-            sVal = "undefined";
-            isNum = false;
-        }
+    /**
+     * fonction appelée lorsque l'utilisateur fait une saisie
+     * @param event valeur du contrôle
+     */
+    private setValue(event: any) {
+        this._fromUI = true;
+        this._uiValue.value = event;
+        this.log(this._uiValue.toString());
+        return this.validateUIValue();
+    }
+
+    /**
+     * fonction appelée lors d'un rafraîchissement de l'UI
+     */
+    ngDoCheck(): void {
+        this.log("ngDoCheck start : " + this.getSParam() + this.getSUIvalue() + this.getSfromUI());
+
+        if (this._fromUI)
+            this.updateMessage(this._uiValue);
         else {
-            if (typeof val === "string") {
-                isNum = String(val).trim() !== "" && !isNaN(+val)
-                sVal = String(val);
+            if (this._paramDef.isDefined) {
+                this.updateMessage(new NumericalString(this._paramDef.v));
+                this._uiValue.value = String(this._paramDef.v);
             }
+            else
+                this.updateMessage(this._uiValue);
         }
-        this.log("ParamInputComponent.validateValue -" + sVal + "-");
 
-        let ok: boolean = true;
-        this._message = undefined;
-        if (!isNum) {
-            ok = false;
-            this._message = "Please enter a numerical value";
-        }
+        this.log("ngDoCheck end : " + this.getSParam() + this.getSUIvalue());
 
-        if (ok) {
-            let nVal = +val;
+        this._fromUI = false;
+    }
+
+    private updateMessage(v: NumericalString) {
+        this.log("updateMessage start :" + this.getSParam() + this.getSfromUI() + this.getSUIvalue(v) + "  message=" + this._message);
+
+        if (v.isNumerical) {
+            this._message = undefined;
 
             try {
-                this._paramDef.v = nVal;
+                this._paramDef.checkValue(v.numericalValue);
             }
             catch (e) {
                 this._message = e;
-                ok = false;
             }
         }
+        else
+            this._message = "Please enter a numerical value";
+
+        this.log("updateMessage end :" + this.getSParam() + this.getSfromUI() + this.getSUIvalue(v) + "  message=" + this._message);
+    }
 
+    private validateUIValue() {
+        this.log("");
+        this.log("validateValue start : val '" + this._uiValue.toString() + "'" + this.getSParam() + this.getSfromUI());
+
+        let ok: boolean = this._uiValue.isNumerical;
+        if (ok) {
+            try {
+                if (!this._paramDef.isDefined || this._paramDef.v != this._uiValue.numericalValue) {
+                    this._paramDef.v = this._uiValue.numericalValue;
+                    this.changeDetector.detectChanges();  // provoque une détection des changements dans les contrôles
+                }
+            }
+            catch (e) {
+                ok = false;
+            }
+        }
 
         if (!ok) {
-            //this._paramDef.undefine();
-            this.log("ParamInputComponent.param " + this._paramDef.toString());
+            this.log("validateValue end : " + this.getSParam());
 
             let err = {
                 rangeError: {
-                    given: val,
+                    // given: val,
+                    given: this._uiValue.toString(),
                     max: 4,
                     min: 0
                 }
@@ -109,20 +186,29 @@ export class ParamInputComponent implements ControlValueAccessor, OnInit {
             return err;
         }
 
-        this.log("ParamInputComponent.param " + this._paramDef.toString());
+        this.log("validateValue end : " + this.getSParam());
         return null;
     }
 
     private log(m: string) {
-        // console.log(m);
+        let t: number = new Date().getTime() - ParamInputComponent._startTime;
+        console.log("ParamInputComponent(" + this._id + ") " + t + " : " + m);
     }
 
     // ControlValueAccessor interface
 
     propagateChange = (_: any) => { };
 
+    /*
+    //From ControlValueAccessor interface
+    writeValue(value: any) {
+        if (value !== this.innerValue) {
+            this.innerValue = value;
+        }
+    }
+    */
     writeValue(value: any) {
-        this.log("ParamInputComponent.writeValue " + value);
+        this.log("writeValue " + value);
     }
 
     registerOnChange(fn: any) {
diff --git a/src/app/param-service/param.service.ts b/src/app/param-service/param.service.ts
index fa5e49fcf3b450e0fc0d1440181d67c5d0d62c41..7b6654feae395f031522ed61ef884c653aeea090 100644
--- a/src/app/param-service/param.service.ts
+++ b/src/app/param-service/param.service.ts
@@ -4,8 +4,8 @@ export class ParamService {
     private _params: ParamDefinition[];
 
     constructor() {
-        this._params = [new ParamDefinition('Q', ParamDomainValue.POS_NULL, 0),
-        new ParamDefinition('Ks', ParamDomainValue.POS, 1)];
+        this._params = [new ParamDefinition('Q', ParamDomainValue.POS_NULL),
+        new ParamDefinition('Ks', ParamDomainValue.POS)];
         for (let p of this._params)
             p.calculability = ParamCalculability.DICHO;
     }