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 : valeur 'undefined' incorrecte", "ERROR_INVALID_AT_POSITION": "Position %s :", "ERROR_LANG_UNSUPPORTED": "Internationalisation : 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",