diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 48eade02f7b3d44b7c105bf62c7aa985ad984597..e20d5253434d242703797cfb785a3a3fda1a78e7 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -46,6 +46,7 @@ import { AppComponent } from "./app.component";
 import { NgParamInputComponent } from "./components/ngparam-input/ngparam-input.component";
 import { FieldSetComponent } from "./components/field-set/field-set.component";
 import { FieldsetContainerComponent } from "./components/fieldset-container/fieldset-container.component";
+import { ParamComputedComponent } from "./components/param-computed/param-computed.component";
 import { ParamFieldLineComponent } from "./components/param-field-line/param-field-line.component";
 import { ParamValuesComponent } from "./components/param-values/param-values.component";
 import { SelectFieldLineComponent } from "./components/select-field-line/select-field-line.component";
@@ -77,9 +78,13 @@ import { DialogLoadSessionComponent } from "./components/dialog-load-session/dia
 import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component";
 
 import { JalhydAsyncModelValidationDirective } from "./directives/jalhyd-async-model-validation.directive";
-import { JalhydModelValidationDirective } from "./directives/jalhyd-model-validation.directive";
+import {
+  JalhydModelValidationDirective,
+  JalhydModelValidationMinDirective,
+  JalhydModelValidationMaxDirective,
+  JalhydModelValidationStepDirective
+} from "./directives/jalhyd-model-validation.directive";
 import { ImmediateErrorStateMatcher } from "./formulaire/immediate-error-state-matcher";
-import { ParamComputedComponent } from "./components/param-computed/param-computed.component";
 
 const appRoutes: Routes = [
   { path: "list", component: CalculatorListComponent },
@@ -148,6 +153,9 @@ const appRoutes: Routes = [
     GraphTypeSelectComponent,
     JalhydAsyncModelValidationDirective,
     JalhydModelValidationDirective,
+    JalhydModelValidationMinDirective,
+    JalhydModelValidationMaxDirective,
+    JalhydModelValidationStepDirective,
     LogComponent,
     LogEntryComponent,
     NgParamInputComponent,
diff --git a/src/app/components/base-param-input/base-param-input.component.ts b/src/app/components/base-param-input/base-param-input.component.ts
index fb65a845cc5c4c2d59a99968641c67d9e9fb5486..f89955f565aacae16b9f9cf676fb607bf8a5c2ed 100644
--- a/src/app/components/base-param-input/base-param-input.component.ts
+++ b/src/app/components/base-param-input/base-param-input.component.ts
@@ -16,6 +16,10 @@ export class NgBaseParam extends Observable {
         this._param = new ParamDefinition(null, symb, d, val);
     }
 
+    public get param() {
+        return this._param;
+    }
+
     public get symbol() {
         return this._param.symbol;
     }
@@ -32,6 +36,18 @@ export class NgBaseParam extends Observable {
         return this._param.checkValue(val);
     }
 
+    public checkMin(min: number): boolean {
+        return this._param.checkMin(min);
+    }
+
+    public checkMax(max: number): boolean {
+        return this._param.checkMax(max);
+    }
+
+    public checkStep(step: number): boolean {
+        return this._param.checkStep(step);
+    }
+
     public setValue(val: number) {
         this._param.setValue(val);
         this.notifyObservers(val);
diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html
index 53718ce0f5d69c711f5d0e0e2af8412932d85482..9ce4c7853638fdcd3f2aa185b1d549f5bfb9dcd7 100644
--- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html
+++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.html
@@ -15,23 +15,47 @@
         <form>
             <mat-form-field>
                 <input matInput class="form-control" type="number" inputmode="numeric" name="min-value" step="0.01"
-                    [placeholder]="uitextValeurMini" [(ngModel)]="param.minValue" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$">
+                    [placeholder]="uitextValeurMini" [(ngModel)]="param.minValue" #min="ngModel" name="min"
+                    [appJalhydModelValidationMin]="param" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$">
 
-                <mat-error>{{ uitextMustBeANumber }}</mat-error>
+                <mat-error *ngIf="min.errors">
+                    <div *ngIf="min.errors.required || min.errors.pattern">
+                        {{ uitextMustBeANumber }}
+                    </div>
+                    <div *ngIf="! min.errors.required && min.errors.jalhydModelMin">
+                        {{ min.errors.jalhydModelMin.message }}
+                    </div>
+                </mat-error>
             </mat-form-field>
 
             <mat-form-field>
                 <input matInput class="form-control" type="number" inputmode="numeric" name="max-value" step="0.01"
-                    [placeholder]="uitextValeurMaxi" [(ngModel)]="param.maxValue" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$">
+                    [placeholder]="uitextValeurMaxi" [(ngModel)]="param.maxValue" #max="ngModel" name="max"
+                    [appJalhydModelValidationMax]="param" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$">
 
-                <mat-error>{{ uitextMustBeANumber }}</mat-error>
+                    <mat-error *ngIf="max.errors">
+                        <div *ngIf="max.errors.required || max.errors.pattern">
+                            {{ uitextMustBeANumber }}
+                        </div>
+                        <div *ngIf="! max.errors.required && max.errors.jalhydModelMax">
+                            {{ max.errors.jalhydModelMax.message }}
+                        </div>
+                    </mat-error>
             </mat-form-field>
 
             <mat-form-field>
                 <input matInput class="form-control" type="number" inputmode="numeric" name="step-value" step="0.01"
-                    [placeholder]="uitextPasVariation" [(ngModel)]="param.stepValue" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$">
+                    [placeholder]="uitextPasVariation" [(ngModel)]="param.stepValue" #step="ngModel" name="step"
+                    [appJalhydModelValidationStep]="param" required pattern="^-?([0-9]*\.)?([0-9]+[Ee]-?)?[0-9]+$">
 
-                <mat-error>{{ uitextMustBeANumber }}</mat-error>
+                    <mat-error *ngIf="step.errors">
+                        <div *ngIf="step.errors.required || step.errors.pattern">
+                            {{ uitextMustBeANumber }}
+                        </div>
+                        <div *ngIf="! step.errors.required && step.errors.jalhydModelStep">
+                            {{ step.errors.jalhydModelStep.message }}
+                        </div>
+                    </mat-error>
             </mat-form-field>
         </form>
     </div>
diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss
index c8602bba0dc8bf4b943720441741f41cb94d6183..dd6b08f1e11f15ebd95e42e01156d0697f38fcfd 100644
--- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss
+++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.scss
@@ -6,6 +6,10 @@ mat-form-field {
         font-size: .8em;
         max-height: 100px;
     }
+
+    mat-error {
+        line-height: 1em;
+    }
 }
 
 .min-max-step-container {
diff --git a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts
index 651702a5d2ecf95e1eb03d448383234fd224565b..f5e1d3c931c034c466ffb6c0b867521bfa9f55d6 100644
--- a/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts
+++ b/src/app/components/dialog-edit-param-values/dialog-edit-param-values.component.ts
@@ -293,60 +293,4 @@ export class DialogEditParamValuesComponent implements OnInit {
     public ngOnInit() {
         this.initVariableValues();
     }
-
-  /*   protected validateModelValue(v: any): { isValid: boolean, message: string } {
-      let msg: string;
-      let valid = false;
-
-      if (this.param === undefined) {
-          msg = "internal error, model undefined";
-      } else {
-          if (!this.param.checkMin(v)) {
-              msg = "La valeur n'est pas dans [" + this.param.domain.minValue + " , " + this.param.maxValue + "[";
-          } else {
-              valid = true;
-          }
-      }
-
-      return { isValid: valid, message: msg };
-  }
-  protected validateModelValue(v: any): { isValid: boolean, message: string } {
-      let msg: string;
-      let valid = false;
-
-      if (this.param === undefined) {
-          msg = "internal error, model undefined";
-      } else {
-          if (!this.param.checkMax(v)) {
-              msg = "La valeur n'est pas dans ]" + this.param.minValue + " , " + this.param.domain.maxValue + "]";
-          } else {
-              valid = true;
-          }
-      }
-
-      return { isValid: valid, message: msg };
-  }
-  protected validateModelValue(v: any): { isValid: boolean, message: string } {
-      let msg: string;
-      let valid = false;
-
-      if (! this.param) {
-          msg = "internal error, model undefined";
-      } else {
-          if (this.param.isMinMaxValid) {
-              if (!this.param.checkStep(v)) {
-                  msg = "La valeur n'est pas dans " + this.param.stepRefValue.toString();
-              } else {
-                  valid = v > 0;
-                  if (!valid) {
-                      msg = "La valeur ne peut pas être <= 0";
-                  }
-              }
-          } else {
-              msg = "Veuillez corriger le min/max";
-          }
-      }
-
-      return { isValid: valid, message: msg };
-  } */
 }
diff --git a/src/app/directives/jalhyd-model-validation.directive.ts b/src/app/directives/jalhyd-model-validation.directive.ts
index 06a9bf67363afa05e468202f6417b94247a126be..8d7d527716d035b5cd68f1216744ac21cf607197 100644
--- a/src/app/directives/jalhyd-model-validation.directive.ts
+++ b/src/app/directives/jalhyd-model-validation.directive.ts
@@ -1,6 +1,9 @@
 import { NG_VALIDATORS, Validator, AbstractControl, ValidatorFn } from "@angular/forms";
 import { Directive, Input } from "@angular/core";
 import { NgBaseParam } from "../components/base-param-input/base-param-input.component";
+import { NgParameter } from "../formulaire/ngparam";
+import { sprintf } from "sprintf-js";
+import { ServiceFactory } from "../services/service-factory";
 
 /**
  * Synchronous validator for Ngparam, relying on JaLHyd ParamDefinition model
@@ -22,6 +25,66 @@ export class JalhydModelValidationDirective implements Validator {
     }
 }
 
+/**
+ * Synchronous validator for Ngparam, relying on JaLHyd ParamDefinition checkMin()
+ */
+@Directive({
+    selector: "[appJalhydModelValidationMin]",
+    providers: [ {
+        provide: NG_VALIDATORS,
+        useExisting: JalhydModelValidationMinDirective,
+        multi: true
+    } ]
+})
+export class JalhydModelValidationMinDirective implements Validator {
+    @Input("appJalhydModelValidationMin") ngParam: NgParameter;
+
+    validate(control: AbstractControl): { [key: string]: any } | null {
+        const mv = jalhydModelValidatorMin(this.ngParam)(control);
+        return mv;
+    }
+}
+
+/**
+ * Synchronous validator for Ngparam, relying on JaLHyd ParamDefinition checkMax()
+ */
+@Directive({
+    selector: "[appJalhydModelValidationMax]",
+    providers: [ {
+        provide: NG_VALIDATORS,
+        useExisting: JalhydModelValidationMaxDirective,
+        multi: true
+    } ]
+})
+export class JalhydModelValidationMaxDirective implements Validator {
+    @Input("appJalhydModelValidationMax") ngParam: NgParameter;
+
+    validate(control: AbstractControl): { [key: string]: any } | null {
+        const mv = jalhydModelValidatorMax(this.ngParam)(control);
+        return mv;
+    }
+}
+
+/**
+ * Synchronous validator for Ngparam, relying on JaLHyd ParamDefinition checkStep()
+ */
+@Directive({
+    selector: "[appJalhydModelValidationStep]",
+    providers: [ {
+        provide: NG_VALIDATORS,
+        useExisting: JalhydModelValidationStepDirective,
+        multi: true
+    } ]
+})
+export class JalhydModelValidationStepDirective implements Validator {
+    @Input("appJalhydModelValidationStep") ngParam: NgParameter;
+
+    validate(control: AbstractControl): { [key: string]: any } | null {
+        const mv = jalhydModelValidatorStep(this.ngParam)(control);
+        return mv;
+    }
+}
+
 export function jalhydModelValidator(ngBaseParam: NgBaseParam): ValidatorFn {
     return (control: AbstractControl): { [key: string]: any } | null => {
         let errorReturn = null; // no error, everything OK
@@ -37,3 +100,62 @@ export function jalhydModelValidator(ngBaseParam: NgBaseParam): ValidatorFn {
         return errorReturn;
     };
 }
+
+export function jalhydModelValidatorMin(ngParam: NgParameter): ValidatorFn {
+    return (control: AbstractControl): { [key: string]: any } | null => {
+        let errorReturn = null; // no error, everything OK
+        const result = ngParam.checkMin(control.value);
+        if (! result) {
+            errorReturn = {
+                "jalhydModelMin": {
+                    value: control.value,
+                    message: sprintf(
+                        ServiceFactory.instance.i18nService.localizeText("ERROR_MINMAXSTEP_MIN"),
+                        ngParam.domain.minValue,
+                        ngParam.maxValue
+                    )
+                }
+            };
+        }
+        return errorReturn;
+    };
+}
+
+export function jalhydModelValidatorMax(ngParam: NgParameter): ValidatorFn {
+    return (control: AbstractControl): { [key: string]: any } | null => {
+        let errorReturn = null; // no error, everything OK
+        const result = ngParam.checkMax(control.value);
+        if (! result) {
+            errorReturn = {
+                "jalhydModelMax": {
+                    value: control.value,
+                    message: sprintf(
+                        ServiceFactory.instance.i18nService.localizeText("ERROR_MINMAXSTEP_MAX"),
+                        ngParam.minValue,
+                        ngParam.domain.maxValue
+                    )
+                }
+            };
+        }
+        return errorReturn;
+    };
+}
+
+export function jalhydModelValidatorStep(ngParam: NgParameter): ValidatorFn {
+    return (control: AbstractControl): { [key: string]: any } | null => {
+        let errorReturn = null; // no error, everything OK
+        const result = ngParam.checkStep(control.value);
+        if (! result) {
+            errorReturn = {
+                "jalhydModelStep": {
+                    value: control.value,
+                    message: sprintf(
+                        ServiceFactory.instance.i18nService.localizeText("ERROR_MINMAXSTEP_STEP"),
+                        ngParam.stepRefValue.toString()
+                    )
+                }
+            };
+        }
+        return errorReturn;
+    };
+}
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 34099e643b960efc8817c7fcda4d0e3c7a1225d2..4e0057b97cfc9a65f15972f8dee961f13c8a1693 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -10,6 +10,9 @@
     "ERROR_INTERVAL_UNDEF": "Interval: invalid 'undefined' value",
     "ERROR_INVALID_AT_POSITION": "Position %s:",
     "ERROR_LANG_UNSUPPORTED": "internationalisation: unsupported '%locale%' locale",
+    "ERROR_MINMAXSTEP_MIN": "Value is not in [%s,%s[",
+    "ERROR_MINMAXSTEP_MAX": "Value is not in ]%s,%s]",
+    "ERROR_MINMAXSTEP_STEP": "Value is not in %s",
     "ERROR_NEWTON_DERIVEE_NULLE": "Null function derivative in Newton computation",
     "ERROR_PARAM_NULL": "Parameter value must not be NULL",
     "ERROR_PARAM_MUST_BE_A_NUMBER": "Please type a numeric value",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index 505f25e4aaa91256a7698fe58474de8a03df6644..0b88860267614c05862ab3569966e0fb4a9ac758 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -10,6 +10,9 @@
     "ERROR_INTERVAL_UNDEF": "Interval&nbsp;: valeur 'undefined' incorrecte",
     "ERROR_INVALID_AT_POSITION": "Position %s :",
     "ERROR_LANG_UNSUPPORTED": "Internationalisation&nbsp;: locale '%locale%' non prise en charge",
+    "ERROR_MINMAXSTEP_MIN": "La valeur n'est pas dans [%s,%s[",
+    "ERROR_MINMAXSTEP_MAX": "La valeur n'est pas dans ]%s,%s]",
+    "ERROR_MINMAXSTEP_STEP": "La valeur n'est pas dans %s",
     "ERROR_NEWTON_DERIVEE_NULLE": "Dérivée nulle dans un calcul par la méthode de Newton",
     "ERROR_PARAM_NULL": "La valeur du paramètre ne peut pas être NULL",
     "ERROR_PARAM_MUST_BE_A_NUMBER": "Veuillez entrer une valeur numérique",