From 1930e4d61c838777bf245674f1d8bf69993eca4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Grand?= <francois.grand@inrae.fr>
Date: Tue, 18 Oct 2022 17:19:50 +0200
Subject: [PATCH] refactor: calculator JSON configuration: remove selectIds,
 customSelectIds

refs #483
---
 src/app/calculators/bief/config.json          |  1 -
 src/app/calculators/cloisons/config.json      |  1 -
 src/app/calculators/courberemous/config.json  |  1 -
 src/app/calculators/dever/config.json         |  1 -
 src/app/calculators/espece/config.json        |  1 -
 src/app/calculators/grille/config.json        |  1 -
 src/app/calculators/lechaptcalmon/config.json |  1 -
 .../calculators/macrorugocompound/config.json |  1 -
 src/app/calculators/par/config.json           |  1 -
 .../calculators/parallelstructure/config.json |  1 -
 src/app/calculators/parsimulation/config.json |  1 -
 src/app/calculators/prebarrage/config.json    | 14 -----
 .../calculators/regimeuniforme/config.json    |  1 -
 .../calculators/sectionparametree/config.json |  1 -
 src/app/calculators/solveur/config.json       |  2 -
 src/app/calculators/spp/config.json           |  1 -
 src/app/calculators/trigo/config.json         |  1 -
 src/app/calculators/verificateur/config.json  |  2 -
 .../formulaire/definition/form-definition.ts  |  8 +++
 .../formulaire/definition/form-fixedvar.ts    | 34 ++-----------
 src/app/formulaire/elements/fieldset.ts       | 51 +++++++++----------
 .../select/select-field-device-loi-debit.ts   | 16 +++---
 .../select-field-device-structure-type.ts     | 16 +++---
 .../select/select-field-downstream-basin.ts   |  8 ---
 .../select/select-field-remous-target.ts      | 16 +++---
 .../select/select-field-searched-param.ts     |  8 ---
 .../select-field-solver-targeted-result.ts    | 15 +++---
 .../select/select-field-solveur-target.ts     | 10 +---
 .../select/select-field-species-list.ts       | 10 +---
 .../select/select-field-target-pass.ts        | 10 +---
 .../select/select-field-upstream-basin.ts     | 10 +---
 .../elements/select/select-field.ts           |  7 +++
 .../deep-selectfield-iterator.ts              | 19 +++++++
 33 files changed, 91 insertions(+), 180 deletions(-)
 create mode 100644 src/app/formulaire/form-iterator/deep-selectfield-iterator.ts

diff --git a/src/app/calculators/bief/config.json b/src/app/calculators/bief/config.json
index 7434f2abc..584efa828 100644
--- a/src/app/calculators/bief/config.json
+++ b/src/app/calculators/bief/config.json
@@ -69,7 +69,6 @@
     {
         "type": "options",
         "defaultNodeType": "SectionRectangle",
-        "selectIds": [ "select_section", "select_regime" ],
         "help": "hsl/cote_amont_aval.html"
     }
 ]
diff --git a/src/app/calculators/cloisons/config.json b/src/app/calculators/cloisons/config.json
index 2423ef4bc..e3b2a662d 100644
--- a/src/app/calculators/cloisons/config.json
+++ b/src/app/calculators/cloisons/config.json
@@ -61,7 +61,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_structure", "select_loidebit" ],
         "help": "pab/cloisons.html"
     }
 ]
diff --git a/src/app/calculators/courberemous/config.json b/src/app/calculators/courberemous/config.json
index b66d709bb..30bab2879 100644
--- a/src/app/calculators/courberemous/config.json
+++ b/src/app/calculators/courberemous/config.json
@@ -96,7 +96,6 @@
     {
         "type": "options",
         "defaultNodeType": "SectionRectangle",
-        "selectIds": [ "select_resolution", "select_section", "select_target" ],
         "help": "hsl/courbe_remous.html",
         "resultsHelp": {
             "B": "hsl/section_parametree.html#largeur-au-miroir-surface-et-perimetre-mouille",
diff --git a/src/app/calculators/dever/config.json b/src/app/calculators/dever/config.json
index 6b502f27a..69188b972 100644
--- a/src/app/calculators/dever/config.json
+++ b/src/app/calculators/dever/config.json
@@ -51,7 +51,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_structure", "select_loidebit" ],
         "help": "structures/dever.html"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/espece/config.json b/src/app/calculators/espece/config.json
index 1b6185a5e..71a6f42f7 100644
--- a/src/app/calculators/espece/config.json
+++ b/src/app/calculators/espece/config.json
@@ -94,7 +94,6 @@
     {
         "type": "options",
         "help": "verif/especes_predefinies.html",
-        "selectIds": [ "select_divingjetsupported" ],
         "calculateDisabled": true
     }
 ]
diff --git a/src/app/calculators/grille/config.json b/src/app/calculators/grille/config.json
index e964fa9e3..b01502d19 100644
--- a/src/app/calculators/grille/config.json
+++ b/src/app/calculators/grille/config.json
@@ -96,7 +96,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_gridtype", "select_gridprofile" ],
         "help": "devalaison/grille.html",
         "resultsHelp": {
             "VAPDG": "devalaison/grille.html#vitesse-dapproche-moyenne-pour-le-debit-maximum-turbine-en-soustrayant-la-partie-superieure-eventuellement-obturee",
diff --git a/src/app/calculators/lechaptcalmon/config.json b/src/app/calculators/lechaptcalmon/config.json
index 431552de8..d655d5ca3 100644
--- a/src/app/calculators/lechaptcalmon/config.json
+++ b/src/app/calculators/lechaptcalmon/config.json
@@ -28,7 +28,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_material" ],
         "help": "hyd_en_charge/lechapt-calmon.html"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/macrorugocompound/config.json b/src/app/calculators/macrorugocompound/config.json
index 8df7adca3..79290dc66 100644
--- a/src/app/calculators/macrorugocompound/config.json
+++ b/src/app/calculators/macrorugocompound/config.json
@@ -78,7 +78,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_passtype" ],
         "help": "pam/macrorugo_complexe.html"
     }
 ]
diff --git a/src/app/calculators/par/config.json b/src/app/calculators/par/config.json
index dc6fcb41e..c7ba05c46 100644
--- a/src/app/calculators/par/config.json
+++ b/src/app/calculators/par/config.json
@@ -38,7 +38,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_partype" ],
         "help": "par/calage.html"
     }
 ]
diff --git a/src/app/calculators/parallelstructure/config.json b/src/app/calculators/parallelstructure/config.json
index d265d9a66..87ef99908 100644
--- a/src/app/calculators/parallelstructure/config.json
+++ b/src/app/calculators/parallelstructure/config.json
@@ -74,7 +74,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_structure", "select_loidebit" ],
         "help": "structures/lois_ouvrages.html",
         "resultsHelp": {
             "ENUM_StructureJetType": "structures/lois_ouvrages.html#type-de-jet"
diff --git a/src/app/calculators/parsimulation/config.json b/src/app/calculators/parsimulation/config.json
index a5cb2c9de..810625bf6 100644
--- a/src/app/calculators/parsimulation/config.json
+++ b/src/app/calculators/parsimulation/config.json
@@ -54,7 +54,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_partype" ],
         "help": "par/simulation.html"
     }
 ]
diff --git a/src/app/calculators/prebarrage/config.json b/src/app/calculators/prebarrage/config.json
index 1b0431549..406711a5e 100644
--- a/src/app/calculators/prebarrage/config.json
+++ b/src/app/calculators/prebarrage/config.json
@@ -15,10 +15,6 @@
                     "Z1",
                     "Z2"
                 ]
-            },
-            {
-                "type": "options",
-                "selectIds": [ ]
             }
         ]
     },
@@ -41,10 +37,6 @@
                 "templates": [
                     "fs_basin"
                 ]
-            },
-            {
-                "type": "options",
-                "selectIds": [ ]
             }
         ]
     },
@@ -181,17 +173,11 @@
                 "templates": [
                     "fs_ouvrage"
                 ]
-            },
-            {
-                "type": "options",
-                "selectIds": [ "select_structure", "select_loidebit" ],
-                "customSelectIds": [ "select_upstream_basin", "select_downstream_basin" ]
             }
         ]
     },
     {
         "type": "options",
-        "selectIds": [ ],
         "upstreamSelectId": "select_upstream",
         "downstreamSelectId": "select_downstream",
         "help": "pab/prebarrage.html"
diff --git a/src/app/calculators/regimeuniforme/config.json b/src/app/calculators/regimeuniforme/config.json
index 14a3239ef..171dc0139 100644
--- a/src/app/calculators/regimeuniforme/config.json
+++ b/src/app/calculators/regimeuniforme/config.json
@@ -50,7 +50,6 @@
     {
         "type": "options",
         "defaultNodeType": "SectionRectangle",
-        "selectIds": [ "select_section" ],
         "help": "hsl/regime_uniforme.html",
         "resultsHelp": {
             "V": "hsl/section_parametree.html#la-vitesse-moyenne-ms"
diff --git a/src/app/calculators/sectionparametree/config.json b/src/app/calculators/sectionparametree/config.json
index f24b88ca8..4e4ce5e28 100644
--- a/src/app/calculators/sectionparametree/config.json
+++ b/src/app/calculators/sectionparametree/config.json
@@ -50,7 +50,6 @@
     {
         "type": "options",
         "defaultNodeType": "SectionRectangle",
-        "selectIds": [ "select_section" ],
         "help": "hsl/section_parametree.html",
         "resultsHelp": {
             "B": "hsl/section_parametree.html#largeur-au-miroir-surface-et-perimetre-mouille",
diff --git a/src/app/calculators/solveur/config.json b/src/app/calculators/solveur/config.json
index 99d215264..9c0fd2b31 100644
--- a/src/app/calculators/solveur/config.json
+++ b/src/app/calculators/solveur/config.json
@@ -27,8 +27,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_target_result" ],
-        "customSelectIds": [ "select_target_nub", "select_searched_param" ],
         "targettedResultSelectId": "select_target_result",
         "help": "maths/solver.html"
     }
diff --git a/src/app/calculators/spp/config.json b/src/app/calculators/spp/config.json
index 8506d7c73..e28d38ff8 100644
--- a/src/app/calculators/spp/config.json
+++ b/src/app/calculators/spp/config.json
@@ -31,7 +31,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_sppoperation" ],
         "help": "maths/operators.html#somme-et-produit-de-puissances"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/trigo/config.json b/src/app/calculators/trigo/config.json
index 3b9f5d97a..264fe9299 100644
--- a/src/app/calculators/trigo/config.json
+++ b/src/app/calculators/trigo/config.json
@@ -24,7 +24,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_operation", "select_unit" ],
         "help": "maths/operators.html#fonction-trigonometrique"
     }
 ]
\ No newline at end of file
diff --git a/src/app/calculators/verificateur/config.json b/src/app/calculators/verificateur/config.json
index 07f6f672c..7faef08de 100644
--- a/src/app/calculators/verificateur/config.json
+++ b/src/app/calculators/verificateur/config.json
@@ -21,8 +21,6 @@
     },
     {
         "type": "options",
-        "selectIds": [ "select_pab_jet_type" ],
-        "customSelectIds": [ "select_target_pass", "select_species_list" ],
         "help": "verif/principe.html"
     }
 ]
diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts
index cc5837883..bcf6eef68 100644
--- a/src/app/formulaire/definition/form-definition.ts
+++ b/src/app/formulaire/definition/form-definition.ts
@@ -26,6 +26,7 @@ import { ServiceFactory } from "../../services/service-factory";
 import { PabTable } from "../elements/pab-table";
 import { SelectEntry } from "../elements/select/select-entry";
 import { SelectField } from "../elements/select/select-field";
+import { DeepSelectFieldIterator } from "../form-iterator/deep-selectfield-iterator";
 
 /**
  * classe de base pour tous les formulaires
@@ -410,6 +411,13 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return new TopFormulaireElementIterator(this);
     }
 
+    /**
+     * itère sur tous les SelectField
+     */
+    public get allSelectFields(): IterableIterator<SelectField> {
+        return new DeepSelectFieldIterator(this);
+    }
+
     //  interface Observer
 
     public update(sender: any, data: any) {
diff --git a/src/app/formulaire/definition/form-fixedvar.ts b/src/app/formulaire/definition/form-fixedvar.ts
index 9289094a7..0a329f489 100644
--- a/src/app/formulaire/definition/form-fixedvar.ts
+++ b/src/app/formulaire/definition/form-fixedvar.ts
@@ -14,12 +14,6 @@ export class FormulaireFixedVar extends FormulaireDefinition {
     protected _fixedResults: FixedResults;
     protected _varResults: VarResults;
 
-    /** ids of select fields */
-    private _selectIds: string[] = [];
-
-    /** ids of "custom" select fields */
-    private _customSelectIds: string[] = [];
-
     constructor(parent?: FormulaireNode) {
         super(parent);
         this._fixedResults = new FixedResults();
@@ -31,10 +25,6 @@ export class FormulaireFixedVar extends FormulaireDefinition {
         return this._fixedResults;
     }
 
-    public get selectids(): string[] {
-        return this._selectIds;
-    }
-
     public resetFormResults() {
         this._fixedResults.reset();
         this._varResults.reset();
@@ -73,24 +63,14 @@ export class FormulaireFixedVar extends FormulaireDefinition {
 
     public afterParseFieldset(fs: FieldSet) {
         // observe all Select fields @see this.update()
-        if (this._selectIds.length > 0) {
-            for (const sId of this._selectIds) {
-                const sel = fs.getFormulaireNodeById(sId);
-                if (sel) {
-                    // Formulaire is listening to FieldSet properties (@TODO why not directly Select ?)
-                    fs.properties.addObserver(this);
-                }
-            }
-        }
+        fs.properties.addObserver(this);
     }
 
     protected completeParse(firstNotif: boolean = true) {
         super.completeParse(firstNotif);
         // observe all CustomSelect fields @TODO move to afterParseFieldset ?
-        if (this._customSelectIds.length > 0) {
-            for (const csId of this._customSelectIds) {
-                const sel = this.getFormulaireNodeById(csId);
-                // Formulaire is listening to Select value
+        for (const sel of this.allSelectFields) {  // Formulaire is listening to Select value
+            if (!sel.hasAssociatedNubProperty) { // only to "custom" selects
                 sel.addObserver(this);
                 if (firstNotif) {
                     // force 1st observation
@@ -100,14 +80,6 @@ export class FormulaireFixedVar extends FormulaireDefinition {
         }
     }
 
-    protected parseOptions(json: {}) {
-        super.parseOptions(json);
-        // get ids of all select fields
-        this._selectIds = this.getOption(json, "selectIds") || [];
-        // get ids of all "custom" select fields
-        this._customSelectIds = this.getOption(json, "customSelectIds") || [];
-    }
-
     protected compute() {
         this.runNubCalc(this.currentNub);
         this.refreshFieldsets(); // important: before reaffectResultComponents() or it will break results components localization
diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts
index 89a696bf0..e5fbca7d7 100644
--- a/src/app/formulaire/elements/fieldset.ts
+++ b/src/app/formulaire/elements/fieldset.ts
@@ -15,8 +15,6 @@ import { FieldsetContainer } from "./fieldset-container";
 import { SelectFieldFactory } from "./select/select-field-factory";
 import { FormulaireFixedVar } from "../definition/form-fixedvar";
 import { SelectEntry } from "./select/select-entry";
-import { FormulaireNode } from "./formulaire-node";
-import { ServiceFactory } from "app/services/service-factory";
 
 export class FieldSet extends FormulaireElement implements Observer {
 
@@ -237,9 +235,10 @@ export class FieldSet extends FormulaireElement implements Observer {
         // for all select fields known by the form, set selected value
         // from associated property
         if (this.parentForm instanceof FormulaireFixedVar) {
-            const selectIds = this.parentForm.selectids;
-            for (const sId of selectIds) {
-                this.setSelectValueFromProperty(sId, (this._confId === "fs_section"));
+            for (const sel of this.parentForm.allSelectFields) {
+                if (sel.hasAssociatedNubProperty) {  // ie. if select is a standard select
+                    this.setSelectValueFromProperty(sel.id, (this._confId === "fs_section"));
+                }
             }
         }
     }
@@ -289,13 +288,10 @@ export class FieldSet extends FormulaireElement implements Observer {
         // for all select fields known by the form, apply default value
         // to associated property, usually from associated enum
         if (this.parentForm instanceof FormulaireFixedVar) {
-            const selectIds = this.parentForm.selectids;
-            for (const sId of selectIds) {
-                // find select element in parent form
-                const fe = this.getFormulaireNodeById(sId);
-                if (fe) {
-                    const prop = (fe as SelectField).associatedProperty;
-                    const defaultValue = (fe as SelectField).configDefaultValue;
+            for (const sel of this.parentForm.allSelectFields) {
+                if (sel.hasAssociatedNubProperty) { // ie. if select is a standard select
+                    const prop = sel.associatedProperty;
+                    const defaultValue = sel.configDefaultValue;
                     // Sets Nub default property, unless this property is already set
                     const currentValue = this.properties.getPropValue(prop);
                     if (defaultValue !== undefined && currentValue === undefined) {
@@ -379,28 +375,27 @@ export class FieldSet extends FormulaireElement implements Observer {
                             });
                         }
                     } else {
-                        if (this.parentForm instanceof FormulaireFixedVar) {
-                            // for all select fields known by the form, apply received value
-                            // to associated property
-                            const selectIds = this.parentForm.selectids;
-                            for (const sId of selectIds) {
-                                if (senderId === sId) {
-                                    // find select element in parent form
-                                    const fe = this.parentForm.getFieldById(sId);
-                                    if (fe && data.value !== undefined) {
-                                        const prop = (fe as SelectField).associatedProperty;
-                                        // for multiple select
-                                        if (Array.isArray(data.value)) {
-                                            this.setNubPropValue(prop, data.value.map((v: any) => v.value));
-                                        } else {
-                                            this.setNubPropValue(prop, data.value.value);
+                        if (data.value !== undefined) {
+                            if (this.parentForm instanceof FormulaireFixedVar) {
+                                // for all select fields known by the form, apply received value
+                                // to associated property
+                                for (const sel of this.parentForm.allSelectFields) {
+                                    if (senderId === sel.id) {
+                                        // find select element in parent form
+                                        if (sel.hasAssociatedNubProperty) { // if select is a standard select
+                                            const prop = sel.associatedProperty;
+                                            // for multiple select
+                                            if (Array.isArray(data.value)) {
+                                                this.setNubPropValue(prop, data.value.map((v: any) => v.value));
+                                            } else {
+                                                this.setNubPropValue(prop, data.value.value);
+                                            }
                                         }
                                     }
                                 }
                             }
                         }
                     }
-
                     break; // switch (data.action)
             }
         }
diff --git a/src/app/formulaire/elements/select/select-field-device-loi-debit.ts b/src/app/formulaire/elements/select/select-field-device-loi-debit.ts
index 15194174f..6a9c86e7c 100644
--- a/src/app/formulaire/elements/select/select-field-device-loi-debit.ts
+++ b/src/app/formulaire/elements/select/select-field-device-loi-debit.ts
@@ -1,6 +1,7 @@
 import { LoiDebit, ParallelStructure, StructureProperties, StructureType } from "jalhyd";
 import { SelectField } from "./select-field";
 import { SelectEntry } from "./select-entry";
+import { FormulaireNode } from "../formulaire-node";
 
 /*
     "id": "select_loidebit",
@@ -11,6 +12,11 @@ import { SelectEntry } from "./select-entry";
 */
 
 export class SelectFieldDeviceLoiDebit extends SelectField {
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this._associatedProperty = "loiDebit";
+    }
+
     protected populate() {
         // possible values depend on CalcType
 
@@ -31,12 +37,4 @@ export class SelectFieldDeviceLoiDebit extends SelectField {
     protected initSelectedValue() {
         this.findAndSetDefaultValue();
     }
-
-    public get associatedProperty(): string {
-        return "loiDebit";
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-device-structure-type.ts b/src/app/formulaire/elements/select/select-field-device-structure-type.ts
index b818eedf5..0210eb1b7 100644
--- a/src/app/formulaire/elements/select/select-field-device-structure-type.ts
+++ b/src/app/formulaire/elements/select/select-field-device-structure-type.ts
@@ -1,6 +1,7 @@
 import { ParallelStructure, StructureType } from "jalhyd";
 import { SelectField } from "./select-field";
 import { SelectEntry } from "./select-entry";
+import { FormulaireNode } from "../formulaire-node";
 
 /*
     "id": "select_structure",
@@ -10,6 +11,11 @@ import { SelectEntry } from "./select-entry";
 */
 
 export class SelectFieldDeviceStructureType extends SelectField {
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this._associatedProperty = "structureType";
+    }
+
     protected populate() {
         // possible values depend on CalcType
         for (const st in (this.nub as ParallelStructure).getLoisAdmissibles()) {
@@ -21,12 +27,4 @@ export class SelectFieldDeviceStructureType extends SelectField {
     protected initSelectedValue() {
         this.findAndSetDefaultValue();
     }
-
-    public get associatedProperty(): string {
-        return "structureType";
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-downstream-basin.ts b/src/app/formulaire/elements/select/select-field-downstream-basin.ts
index 77fcab4bd..05675917d 100644
--- a/src/app/formulaire/elements/select/select-field-downstream-basin.ts
+++ b/src/app/formulaire/elements/select/select-field-downstream-basin.ts
@@ -42,12 +42,4 @@ export class SelectFieldDownstreamBasin extends SelectField {
         const db = (this.nub as PbCloison).bassinAval;
         this.setValueFromId(this._entriesBaseId + (db ? db.uid : "none"));
     }
-
-    public get associatedProperty(): string {
-        return undefined;
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
 }
diff --git a/src/app/formulaire/elements/select/select-field-remous-target.ts b/src/app/formulaire/elements/select/select-field-remous-target.ts
index 6d0f2c506..20b40cc47 100644
--- a/src/app/formulaire/elements/select/select-field-remous-target.ts
+++ b/src/app/formulaire/elements/select/select-field-remous-target.ts
@@ -1,6 +1,7 @@
 import { CourbeRemous } from "jalhyd";
 import { SelectField } from "./select-field";
 import { SelectEntry } from "./select-entry";
+import { FormulaireNode } from "../formulaire-node";
 
 /*
     "id": "select_target",
@@ -11,6 +12,11 @@ import { SelectEntry } from "./select-entry";
 */
 
 export class SelectFieldRemousTarget extends SelectField {
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this._associatedProperty = "varCalc";
+    }
+
     protected populate() {
         // driven by string[], not enum (easier for variable names)
         this.addEntry(new SelectEntry(this._entriesBaseId + "none", ""));
@@ -23,12 +29,4 @@ export class SelectFieldRemousTarget extends SelectField {
     protected initSelectedValue() {
         this.findAndSetDefaultValue();
     }
-
-    public get associatedProperty(): string {
-        return "varCalc";
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-searched-param.ts b/src/app/formulaire/elements/select/select-field-searched-param.ts
index 5380e1238..1342fb643 100644
--- a/src/app/formulaire/elements/select/select-field-searched-param.ts
+++ b/src/app/formulaire/elements/select/select-field-searched-param.ts
@@ -48,14 +48,6 @@ export class SelectFieldSearchedParam extends SelectField {
         }
     }
 
-    public get associatedProperty(): string {
-        return undefined;
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-
     public updateLocalisation() {
         // do not override localisation done in populate()
         // ie. avoid what is done by SelectField.updateLocalisation()
diff --git a/src/app/formulaire/elements/select/select-field-solver-targeted-result.ts b/src/app/formulaire/elements/select/select-field-solver-targeted-result.ts
index 2b10da827..a547bde3c 100644
--- a/src/app/formulaire/elements/select/select-field-solver-targeted-result.ts
+++ b/src/app/formulaire/elements/select/select-field-solver-targeted-result.ts
@@ -4,6 +4,7 @@ import { Nub, Solveur } from "jalhyd";
 import { FormulaireElement } from "../formulaire-element";
 import { SelectField } from "./select-field";
 import { SelectEntry } from "./select-entry";
+import { FormulaireNode } from "../formulaire-node";
 
 /*
     "id": "select_target_result",
@@ -13,6 +14,10 @@ import { SelectEntry } from "./select-entry";
     "default": ""
 */
 export class SelectFieldSolverTargetedResult extends SelectField {
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this._associatedProperty = "targettedResult";
+    }
 
     protected populate() {
         // @WARNING for localisation, @see hack in this.updateLocalisation()
@@ -34,14 +39,6 @@ export class SelectFieldSolverTargetedResult extends SelectField {
         this.findAndSetDefaultValue();
     }
 
-    public get configDefaultValue(): string {
-        return "";
-    }
-
-    public get associatedProperty(): string {
-        return "targettedResult";
-    }
-
     public updateLocalisation() {
         FormulaireElement.prototype.updateLocalisation.call(this);
         for (const e of this._entries) {
@@ -61,4 +58,4 @@ export class SelectFieldSolverTargetedResult extends SelectField {
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-solveur-target.ts b/src/app/formulaire/elements/select/select-field-solveur-target.ts
index 64d37dc33..aecd238b8 100644
--- a/src/app/formulaire/elements/select/select-field-solveur-target.ts
+++ b/src/app/formulaire/elements/select/select-field-solveur-target.ts
@@ -47,16 +47,8 @@ export class SelectFieldSolverTarget extends SelectField {
         }
     }
 
-    public get associatedProperty(): string {
-        return undefined;
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-
     public updateLocalisation() {
         // do not override localisation done in populate()
         // ie. avoid what is done by SelectField.updateLocalisation()
     }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-species-list.ts b/src/app/formulaire/elements/select/select-field-species-list.ts
index bcdbbee79..602a56854 100644
--- a/src/app/formulaire/elements/select/select-field-species-list.ts
+++ b/src/app/formulaire/elements/select/select-field-species-list.ts
@@ -58,16 +58,8 @@ export class SelectFieldSpeciesList extends SelectField {
         }
     }
 
-    public get associatedProperty(): string {
-        return undefined;
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-
     public updateLocalisation() {
         // do not override localisation done in populate()
         // ie. avoid what is done by SelectField.updateLocalisation()
     }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-target-pass.ts b/src/app/formulaire/elements/select/select-field-target-pass.ts
index 36430d217..10cd639a1 100644
--- a/src/app/formulaire/elements/select/select-field-target-pass.ts
+++ b/src/app/formulaire/elements/select/select-field-target-pass.ts
@@ -47,16 +47,8 @@ export class SelectFieldTargetPass extends SelectField {
         }
     }
 
-    public get associatedProperty(): string {
-        return undefined;
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-
     public updateLocalisation() {
         // do not override localisation done in populate()
         // ie. avoid what is done by SelectField.updateLocalisation()
     }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field-upstream-basin.ts b/src/app/formulaire/elements/select/select-field-upstream-basin.ts
index 06e335f5c..0eeb6b605 100644
--- a/src/app/formulaire/elements/select/select-field-upstream-basin.ts
+++ b/src/app/formulaire/elements/select/select-field-upstream-basin.ts
@@ -42,12 +42,4 @@ export class SelectFieldUpstreamBasin extends SelectField {
         const ub = (this.nub as PbCloison).bassinAmont;
         this.setValueFromId(this._entriesBaseId + (ub ? ub.uid : "none"));
     }
-
-    public get associatedProperty(): string {
-        return undefined;
-    }
-
-    public get configDefaultValue(): string {
-        return undefined;
-    }
-}
\ No newline at end of file
+}
diff --git a/src/app/formulaire/elements/select/select-field.ts b/src/app/formulaire/elements/select/select-field.ts
index 435d042f3..f67c07404 100644
--- a/src/app/formulaire/elements/select/select-field.ts
+++ b/src/app/formulaire/elements/select/select-field.ts
@@ -173,6 +173,13 @@ export abstract class SelectField extends Field {
         return this._associatedProperty;
     }
 
+    /**
+     * @returns true if select field is associated to a nub property
+     */
+    public get hasAssociatedNubProperty(): boolean {
+        return this._associatedProperty !== undefined;
+    }
+
     /**
      * default value from configuration
      */
diff --git a/src/app/formulaire/form-iterator/deep-selectfield-iterator.ts b/src/app/formulaire/form-iterator/deep-selectfield-iterator.ts
new file mode 100644
index 000000000..6c8547543
--- /dev/null
+++ b/src/app/formulaire/form-iterator/deep-selectfield-iterator.ts
@@ -0,0 +1,19 @@
+import { AbstractFormulaireNodeIterator } from "./abstract-node-iterator";
+import { FormulaireNode } from "../elements/formulaire-node";
+import { SelectField } from "../elements/select/select-field";
+
+/**
+ * itérateur qui extrait récursivement les SelectField dans un tableau de FormulaireElement
+ * (qui peut contenir des FieldsetContainer)
+ */
+export class DeepSelectFieldIterator extends AbstractFormulaireNodeIterator<SelectField> implements IterableIterator<SelectField> {
+    protected isIterable(fe: FormulaireNode) {
+        return fe instanceof SelectField;
+    }
+
+    // interface IterableIterator
+
+    [Symbol.iterator](): IterableIterator<SelectField> {
+        return this;
+    }
+}
-- 
GitLab