diff --git a/src/app/calculators/bief/config.json b/src/app/calculators/bief/config.json
index 95f2ca549d1b5dc05e6a6b4a750015c93ceca321..7434f2abcf9bed90ed8d8f0779ee1f9f50c8b09f 100644
--- a/src/app/calculators/bief/config.json
+++ b/src/app/calculators/bief/config.json
@@ -72,4 +72,4 @@
         "selectIds": [ "select_section", "select_regime" ],
         "help": "hsl/cote_amont_aval.html"
     }
-]
\ No newline at end of file
+]
diff --git a/src/app/calculators/cloisons/config.json b/src/app/calculators/cloisons/config.json
index 82ccf331ee69f680da4dc26b1dc593fd26d58406..2423ef4bc3b405f01736a6b9f1fe2892cd599d03 100644
--- a/src/app/calculators/cloisons/config.json
+++ b/src/app/calculators/cloisons/config.json
@@ -21,15 +21,11 @@
         "fields": [
             {
                 "id": "select_structure",
-                "type": "select",
-                "property": "structureType",
-                "source": "device_structure_type"
+                "type": "select"
             },
             {
                 "id": "select_loidebit",
                 "type": "select",
-                "property": "loiDebit",
-                "source": "device_loi_debit",
                 "help": {
                     "OrificeSubmerged": "structures/orifice_noye.html",
                     "WeirSubmergedLarinier": "structures/fente_noyee.html",
diff --git a/src/app/calculators/courberemous/config.json b/src/app/calculators/courberemous/config.json
index 272de86872224c219f6fe666b9a56243dab70180..b66d709bb5e4717bb1f6b868cca3f7274cb7e64e 100644
--- a/src/app/calculators/courberemous/config.json
+++ b/src/app/calculators/courberemous/config.json
@@ -72,8 +72,6 @@
             {
                 "id": "select_target",
                 "type": "select",
-                "property": "varCalc",
-                "source": "remous_target",
                 "help": {
                     "B": "hsl/section_parametree.html#largeur-au-miroir-surface-et-perimetre-mouille",
                     "P": "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 ce6bea142fe35ea06a1cc374aad7ed5745fa9757..6b502f27a57751d79ec687c5b18bb6f92382a2b7 100644
--- a/src/app/calculators/dever/config.json
+++ b/src/app/calculators/dever/config.json
@@ -19,15 +19,11 @@
         "fields": [
             {
                 "id": "select_structure",
-                "type": "select",
-                "property": "structureType",
-                "source": "device_structure_type"
+                "type": "select"
             },
             {
                 "id": "select_loidebit",
                 "type": "select",
-                "property": "loiDebit",
-                "source": "device_loi_debit",
                 "help": {
                     "WeirFree": "structures/seuil_denoye.html",
                     "TriangularWeirFree": "structures/dever_triang.html",
diff --git a/src/app/calculators/parallelstructure/config.json b/src/app/calculators/parallelstructure/config.json
index 26c3cf9a4414b5e672b7f5dc88a34ac15195da06..d265d9a66e0b0cf6edd589a02f055f11580ba82d 100644
--- a/src/app/calculators/parallelstructure/config.json
+++ b/src/app/calculators/parallelstructure/config.json
@@ -18,15 +18,11 @@
         "fields": [
             {
                 "id": "select_structure",
-                "type": "select",
-                "property": "structureType",
-                "source": "device_structure_type"
+                "type": "select"
             },
             {
                 "id": "select_loidebit",
                 "type": "select",
-                "property": "loiDebit",
-                "source": "device_loi_debit",
                 "help": {
                     "KIVI": "structures/kivi.html",
                     "WeirVillemonte": "structures/kivi.html",
diff --git a/src/app/calculators/prebarrage/config.json b/src/app/calculators/prebarrage/config.json
index 7dada6df94c09621a3c55d9ba3475b3e2298a9f6..1b0431549caae933ad6a26ae1a20c38c76194994 100644
--- a/src/app/calculators/prebarrage/config.json
+++ b/src/app/calculators/prebarrage/config.json
@@ -61,15 +61,11 @@
                 "fields": [
                     {
                         "id": "select_structure",
-                        "type": "select",
-                        "property": "structureType",
-                        "source": "device_structure_type"
+                        "type": "select"
                     },
                     {
                         "id": "select_loidebit",
                         "type": "select",
-                        "property": "loiDebit",
-                        "source": "device_loi_debit",
                         "help": {
                             "KIVI": "structures/kivi.html",
                             "WeirVillemonte": "structures/kivi.html",
@@ -171,13 +167,11 @@
                 "fields": [
                     {
                         "id": "select_upstream_basin",
-                        "type": "select_custom",
-                        "source": "upstream_basin"
+                        "type": "select"
                     },
                     {
                         "id": "select_downstream_basin",
-                        "type": "select_custom",
-                        "source": "downstream_basin"
+                        "type": "select"
                     }
                 ]
             },
diff --git a/src/app/calculators/solveur/config.json b/src/app/calculators/solveur/config.json
index 71a23177b300afc843f27e7c3eed29817fca5aeb..99d21526468c8ba6dc2e4df8990a5307585a14c1 100644
--- a/src/app/calculators/solveur/config.json
+++ b/src/app/calculators/solveur/config.json
@@ -5,15 +5,11 @@
         "fields": [
             {
                 "id": "select_target_nub",
-                "type": "select_custom",
-                "source": "solveur_target"
+                "type": "select"
             },
             {
                 "id": "select_target_result",
-                "type": "select",
-                "property": "targettedResult",
-                "source": "solveur_targetted_result",
-                "default": ""
+                "type": "select"
             },
             "Ytarget"
         ]
@@ -24,8 +20,7 @@
         "fields": [
             {
                 "id": "select_searched_param",
-                "type": "select_custom",
-                "source": "solveur_searched"
+                "type": "select"
             },
             "Xinit"
         ]
diff --git a/src/app/calculators/verificateur/config.json b/src/app/calculators/verificateur/config.json
index 438d2bf32cc332050660af1651db011636be0891..07f6f672c080191ef17b12f6dcbe253dc78694a8 100644
--- a/src/app/calculators/verificateur/config.json
+++ b/src/app/calculators/verificateur/config.json
@@ -5,9 +5,7 @@
         "fields": [
             {
                 "id": "select_target_pass",
-                "type": "select_custom",
-                "source": "verificateur_target",
-                "messageWhenEmpty": "INFO_VERIF_CREATE_PASS_FRIST"
+                "type": "select"
             }
         ]
     },
@@ -16,10 +14,8 @@
         "type": "fieldset",
         "fields": [
             {
-                "type": "select_custom",
-                "id": "select_species_list",
-                "source": "verificateur_species",
-                "multiple": true
+                "type": "select",
+                "id": "select_species_list"
             }
         ]
     },
diff --git a/src/app/components/field-set/field-set.component.ts b/src/app/components/field-set/field-set.component.ts
index 293fce6e21ae0b137e9a6035b2d20e163739e269..448d40a7dc63bfcd47dbec4e10bdb29ba884e857 100644
--- a/src/app/components/field-set/field-set.component.ts
+++ b/src/app/components/field-set/field-set.component.ts
@@ -5,7 +5,7 @@ import { FieldSet } from "../../formulaire/elements/fieldset";
 import { ParamFieldLineComponent } from "../param-field-line/param-field-line.component";
 import { Field } from "../../formulaire/elements/field";
 import { InputField } from "../../formulaire/elements/input-field";
-import { SelectField } from "../../formulaire/elements/select-field";
+import { SelectField } from "../../formulaire/elements/select/select-field";
 import { FormulairePab } from "../../formulaire/definition/form-pab";
 import { SelectFieldLineComponent } from "../select-field-line/select-field-line.component";
 import { FieldsetContainer } from "../../formulaire/elements/fieldset-container";
diff --git a/src/app/components/generic-select/generic-select.component.html b/src/app/components/generic-select/generic-select.component.html
index 9c6880e13e8913f9b7ff1d8073d4df4f5df4ddd0..7ce918d760dc2dd81118e05ed988801c93b960fb 100644
--- a/src/app/components/generic-select/generic-select.component.html
+++ b/src/app/components/generic-select/generic-select.component.html
@@ -23,4 +23,4 @@
 </mat-form-field>
 <div *ngIf="messageWhenEmpty" class="message-when-empty">
     {{ messageWhenEmpty }}
-</div>
\ No newline at end of file
+</div>
diff --git a/src/app/components/select-field-line/select-field-line.component.ts b/src/app/components/select-field-line/select-field-line.component.ts
index eccc37a991e5cdb7462c7f1ec2caddcb3c2ddb5e..2b8cb3a0316f47dcca30ab2727043de814211284 100644
--- a/src/app/components/select-field-line/select-field-line.component.ts
+++ b/src/app/components/select-field-line/select-field-line.component.ts
@@ -1,10 +1,9 @@
 import { Component, Input, OnInit } from "@angular/core";
 
-import { SelectField } from "../../formulaire/elements/select-field";
-import { SelectEntry } from "../../formulaire/elements/select-entry";
+import { SelectField } from "../../formulaire/elements/select/select-field";
+import { SelectEntry } from "../../formulaire/elements/select/select-entry";
 import { I18nService } from "../../services/internationalisation.service";
 import { ApplicationSetupService } from "../../services/app-setup.service";
-import { SelectFieldCustom } from "../../formulaire/elements/select-field-custom";
 import { decodeHtml } from "../../util";
 
 @Component({
@@ -124,8 +123,6 @@ export class SelectFieldLineComponent implements OnInit {
 
     // called every time we navigate to the module
     ngOnInit(): void {
-        if (this._select instanceof SelectFieldCustom) {
-            this._select.updateEntries();
-        }
+        this._select.updateEntries();
     }
 }
diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts
index 814db2e708fde90832361c51d496bf8a6c0531c2..cc5837883349385c3a97201ddfa4cad979dad1b1 100644
--- a/src/app/formulaire/definition/form-definition.ts
+++ b/src/app/formulaire/definition/form-definition.ts
@@ -24,8 +24,8 @@ import { TopFormulaireElementIterator } from "../form-iterator/top-element-itera
 import { CalculatorResults } from "../../results/calculator-results";
 import { ServiceFactory } from "../../services/service-factory";
 import { PabTable } from "../elements/pab-table";
-import { SelectEntry } from "../elements/select-entry";
-import { SelectField } from "../elements/select-field";
+import { SelectEntry } from "../elements/select/select-entry";
+import { SelectField } from "../elements/select/select-field";
 
 /**
  * classe de base pour tous les formulaires
diff --git a/src/app/formulaire/definition/form-fixedvar.ts b/src/app/formulaire/definition/form-fixedvar.ts
index 575f7cb100cff6c9f2a3061ce3c27f2812f9e747..9289094a7d9e0b701ee8f73b092b0da3c73bebbb 100644
--- a/src/app/formulaire/definition/form-fixedvar.ts
+++ b/src/app/formulaire/definition/form-fixedvar.ts
@@ -2,12 +2,11 @@ import { FormulaireDefinition } from "./form-definition";
 import { FixedResults } from "../../results/fixed-results";
 import { VarResults } from "../../results/var-results";
 import { ChartType } from "../../results/chart-type";
-import { CalculatorResults } from "../../results/calculator-results";
-import { ParamRadioConfig, NgParameter } from "../elements/ngparam";
+import { NgParameter } from "../elements/ngparam";
 import { FieldSet } from "../elements/fieldset";
 import { FormulaireNode } from "../elements/formulaire-node";
 
-import { SelectFieldCustom } from "../elements/select-field-custom";
+import { SelectField } from "../elements/select/select-field";
 import { Nub, IObservable, VariatedDetails } from "jalhyd";
 
 export class FormulaireFixedVar extends FormulaireDefinition {
@@ -95,7 +94,7 @@ export class FormulaireFixedVar extends FormulaireDefinition {
                 sel.addObserver(this);
                 if (firstNotif) {
                     // force 1st observation
-                    (sel as SelectFieldCustom).notifyValueChanged();
+                    (sel as SelectField).notifyValueChanged();
                 }
             }
         }
diff --git a/src/app/formulaire/definition/form-parallel-structures.ts b/src/app/formulaire/definition/form-parallel-structures.ts
index 9e4dd86d6b05615acc3555d9b8fc6b1441870589..d25b4df33b65a884466b0fde0c01d9e8f1db1b73 100644
--- a/src/app/formulaire/definition/form-parallel-structures.ts
+++ b/src/app/formulaire/definition/form-parallel-structures.ts
@@ -2,7 +2,7 @@ import { Structure, Nub, ParallelStructure, StructureProperties, Props, Session,
 
 import { FieldsetContainer } from "../elements/fieldset-container";
 import { FieldSet } from "../elements/fieldset";
-import { SelectField } from "../elements/select-field";
+import { SelectField } from "../elements/select/select-field";
 import { NgParameter } from "../elements/ngparam";
 import { FieldsetTemplate } from "../elements/fieldset-template";
 import { FormulaireNode } from "../elements/formulaire-node";
diff --git a/src/app/formulaire/definition/form-pb-cloison.ts b/src/app/formulaire/definition/form-pb-cloison.ts
index 02934c401468a2fd0034bd5e506b6b2bee16b7cf..25910c87d6a1ed5681bd8d7af9e5a45092f876c0 100644
--- a/src/app/formulaire/definition/form-pb-cloison.ts
+++ b/src/app/formulaire/definition/form-pb-cloison.ts
@@ -5,7 +5,7 @@ import { FieldSet } from "../elements/fieldset";
 import { FormulaireNode } from "../elements/formulaire-node";
 import { FieldsetContainer } from "../elements/fieldset-container";
 import { FormulairePrebarrage } from "./form-prebarrage";
-import { SelectFieldCustom } from "../elements/select-field-custom";
+import { SelectField } from "../elements/select/select-field";
 import { ServiceFactory } from "app/services/service-factory";
 
 export class FormulairePbCloison extends FormulaireParallelStructure {
@@ -41,7 +41,7 @@ export class FormulairePbCloison extends FormulaireParallelStructure {
             }
         }
 
-        if (sender instanceof SelectFieldCustom) {
+        if (sender instanceof SelectField) {
             const nub = this._currentNub as PbCloison;
             const pb = nub.parent;
             const emptyFields: boolean = ServiceFactory.applicationSetupService.enableEmptyFieldsOnFormInit;
diff --git a/src/app/formulaire/definition/form-solveur.ts b/src/app/formulaire/definition/form-solveur.ts
index 481ea5f6d53bdc020197e68d0828bbbecb0e2212..f658c98eefb762eece2bae95a7180273a8f307ae 100644
--- a/src/app/formulaire/definition/form-solveur.ts
+++ b/src/app/formulaire/definition/form-solveur.ts
@@ -1,9 +1,8 @@
 import { IObservable, ParamDefinition, Nub } from "jalhyd";
 
-import { SelectFieldCustom } from "../elements/select-field-custom";
 import { NgParameter } from "../elements/ngparam";
 import { FormulaireFixedVar } from "./form-fixedvar";
-import { SelectField } from "../elements/select-field";
+import { SelectField } from "../elements/select/select-field";
 import { FieldSet } from "../elements/fieldset";
 
 /**
@@ -52,7 +51,7 @@ export class FormulaireSolveur extends FormulaireFixedVar {
             this.reset();
         }
 
-        if (sender instanceof SelectFieldCustom) {
+        if (sender instanceof SelectField) {
             if (sender.id === "select_target_nub" && data.action === "select") {
                 // update Solveur property: Nub to calculate
                 try {
@@ -95,7 +94,7 @@ export class FormulaireSolveur extends FormulaireFixedVar {
      * Re-populate searched parameter selector with fresh entries
      */
     private refreshParameterEntries() {
-        const pSel = this.getFormulaireNodeById("select_searched_param") as SelectFieldCustom;
+        const pSel = this.getFormulaireNodeById("select_searched_param") as SelectField;
         if (pSel) {
             pSel.updateEntries();
             // reflect changes in GUI
diff --git a/src/app/formulaire/definition/form-verificateur.ts b/src/app/formulaire/definition/form-verificateur.ts
index 3bcd463a65b77779aea4aa3ba7875ddae91adcac..893754665a7cb997437bf7ab7aaa26b6643c9695 100644
--- a/src/app/formulaire/definition/form-verificateur.ts
+++ b/src/app/formulaire/definition/form-verificateur.ts
@@ -1,9 +1,8 @@
 import { IObservable, Nub, Verificateur, Result, VariatedDetails } from "jalhyd";
 
-import { SelectFieldCustom } from "../elements/select-field-custom";
+import { SelectField } from "../elements/select/select-field";
 import { FormulaireFixedVar } from "./form-fixedvar";
 import { VerificateurResults } from "../../results/verificateur-results";
-import { CalculatorResults } from "../../results/calculator-results";
 import { ServiceFactory } from "../../services/service-factory";
 
 /**
@@ -94,7 +93,7 @@ export class FormulaireVerificateur extends FormulaireFixedVar {
             this.reset();
         }
 
-        if (sender instanceof SelectFieldCustom) {
+        if (sender instanceof SelectField) {
             this.reset(); // reset results
             if (sender.id === "select_target_pass" && data.action === "select") {
                 // update Verificateur property: Pass to check
diff --git a/src/app/formulaire/elements/fieldset.ts b/src/app/formulaire/elements/fieldset.ts
index 65200665a7691b92561e19617814eec0510b63e5..4a67910e488fcc0f0b9143fa8d63b3a30cb99b11 100644
--- a/src/app/formulaire/elements/fieldset.ts
+++ b/src/app/formulaire/elements/fieldset.ts
@@ -9,12 +9,12 @@ import {
 
 import { FormulaireElement } from "./formulaire-element";
 import { Field } from "./field";
-import { SelectField } from "./select-field";
+import { SelectField } from "./select/select-field";
 import { NgParameter, ParamRadioConfig } from "./ngparam";
 import { FieldsetContainer } from "./fieldset-container";
-import { SelectFieldCustom } from "./select-field-custom";
+import { SelectFieldFactory } from "./select/select-field-factory";
 import { FormulaireFixedVar } from "../definition/form-fixedvar";
-import { SelectEntry } from "./select-entry";
+import { SelectEntry } from "./select/select-entry";
 import { FormulaireNode } from "./formulaire-node";
 import { ServiceFactory } from "app/services/service-factory";
 
@@ -109,18 +109,7 @@ export class FieldSet extends FormulaireElement implements Observer {
     }
 
     private parse_select(json: {}): SelectField {
-        const res: SelectField = new SelectField(this);
-        res.parseConfig(json);
-        res.addObserver(this);
-        return res;
-    }
-
-    private parse_select_custom(json: {}): SelectField {
-        const source = json["source"];
-        if (source === undefined || source === "") {
-            throw new Error(`Fieldset.parse_select_custom(): "source" must not be empty`);
-        }
-        const res: SelectField = new SelectFieldCustom(this);
+        const res: SelectField = SelectFieldFactory.newSelectField(json, this);
         res.parseConfig(json);
         res.addObserver(this);
         return res;
@@ -225,12 +214,6 @@ export class FieldSet extends FormulaireElement implements Observer {
                     param = this.parse_select(field);
                     this.addField(param);
                     break;
-
-                case "select_custom":
-                    param = this.parse_select_custom(field);
-                    this.addField(param);
-                    break;
-
             }
         }
     }
@@ -311,7 +294,7 @@ export class FieldSet extends FormulaireElement implements Observer {
                 const fe = this.getFormulaireNodeById(sId);
                 if (fe) {
                     const prop = (fe as SelectField).associatedProperty;
-                    const defaultValue = (fe as SelectField).defaultValue;
+                    const defaultValue = (fe as SelectField).configDefaultValue;
                     // Sets Nub default property, unless this property is already set
                     const currentValue = this.properties.getPropValue(prop);
                     if (defaultValue !== undefined && currentValue === undefined) {
diff --git a/src/app/formulaire/elements/select-field-custom.ts b/src/app/formulaire/elements/select-field-custom.ts
deleted file mode 100644
index 5c395281e5840ac070e79ad385bf96e4f806e4f2..0000000000000000000000000000000000000000
--- a/src/app/formulaire/elements/select-field-custom.ts
+++ /dev/null
@@ -1,343 +0,0 @@
-import { SelectEntry } from "./select-entry";
-import { ServiceFactory } from "../../services/service-factory";
-import { SelectField } from "./select-field";
-import { decodeHtml, arraysAreEqual } from "../../util";
-
-import { FishSpecies, Session, Solveur, FishPass, CalculatorType, Verificateur, Nub, PbCloison, PreBarrage, acSection } from "jalhyd";
-
-import { sprintf } from "sprintf-js";
-
-/**
- * A select field that populates itself with custom stuff (ex: references to Nubs, Parameters…)
- */
-export class SelectFieldCustom extends SelectField {
-
-    /**
-     * Loads UI with the value held by the model
-     */
-    protected initSelectedValue() {
-        const nub = this.parentForm.currentNub;
-
-        switch (this.source) {
-
-            case "solveur_target": // Solveur, module cible (à calculer)
-                const ntc = (nub as Solveur).nubToCalculate;
-                if (ntc !== undefined) {
-                    this.setValueFromId(this._entriesBaseId + ntc.uid);
-                }
-                break;
-
-            case "solveur_searched": // Solveur, paramètre recherché (à faire varier)
-                const sp = (nub as Solveur).searchedParameter;
-                if (sp !== undefined) {
-                    let parentNubUid;
-                    const parentNub = sp.getParentComputeNode(false);
-                    if (parentNub instanceof acSection) {
-                        parentNubUid = parentNub.uid;
-                    }
-                    else {
-                        parentNubUid = sp.nubUid
-                    }
-                    this.setValueFromId(this._entriesBaseId + parentNubUid + "_" + sp.symbol);
-                }
-                break;
-
-            case "verificateur_target": // Vérificateur, passe cible (à vérifier)
-                const ntv = (nub as Verificateur).nubToVerify;
-                if (ntv !== undefined) {
-                    this.setValueFromId(this._entriesBaseId + ntv.uid);
-                }
-                break;
-
-            case "verificateur_species": // Vérificateur, liste d'espèces (choix multiple)
-                const sl = (nub as Verificateur).speciesList;
-                if (sl !== undefined) {
-                    this.setValueFromId(sl.map((s) => {
-                        const spgId = s.substring(s.lastIndexOf("_") + 1);
-                        return this._entriesBaseId + spgId;
-                    }));
-                }
-                break;
-
-            case "upstream_basin": // PbCloisons, bassin amont
-                const ub = (nub as PbCloison).bassinAmont;
-                // console.log("-- load UB", ub, this._entriesBaseId + ub?.uid);
-                this.setValueFromId(this._entriesBaseId + (ub ? ub.uid : "none"));
-                break;
-
-            case "downstream_basin": // PbCloisons, bassin aval
-                const db = (nub as PbCloison).bassinAval;
-                // console.log("-- load DB", db, this._entriesBaseId + db?.uid);
-                this.setValueFromId(this._entriesBaseId + (db ? db.uid : "none"));
-                break;
-        }
-    }
-
-    /**
-     * Populates entries with available options
-     */
-    protected populate() {
-        const fs = ServiceFactory.formulaireService;
-        let candidateNubs: any[];
-        switch (this.source) {
-
-            case "solveur_target": // Solveur, module cible (à calculer)
-                // find all Nubs having at least one link to another Nub's result
-                candidateNubs =
-                    Session.getInstance().getDownstreamNubs().concat(
-                        Session.getInstance().getUpstreamNubsHavingExtraResults()
-                    ).filter(
-                        (element, index, self) => self.findIndex((e) => e.uid === element.uid) === index
-                    );
-                for (const cn of candidateNubs) {
-                    const nub = fs.getFormulaireFromId(cn.uid);
-                    if (nub) {
-                        const calc = nub.calculatorName;
-                        let label = calc;
-                        // calculated param
-                        if (cn.calculatedParam !== undefined) {
-                            const varName = fs.expandVariableName(cn.calcType, cn.calculatedParam.symbol);
-                            label += ` / ${varName} (${cn.calculatedParam.symbol})`;
-                        }
-                        this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label)));
-                    } else {
-                        // silent fail, this Solveur nub was probably loaded before all the candidate nubs are done loading
-                    }
-                }
-                break;
-
-            case "solveur_searched": // Solveur, paramètre recherché (à faire varier)
-                // find all non-calculated, non-linked parameters of all Nubs that
-                // the current "target" Nub depends on (if any)
-                const solv = this.parentForm.currentNub as Solveur;
-                const ntc: Nub = solv.nubToCalculate;
-                const searchableParams = Solveur.getDependingNubsSearchableParams(
-                    ntc,
-                    solv.targettedResult !== undefined && solv.targettedResult !== ""
-                );
-                for (const p of searchableParams) {
-                    if (p.visible) {
-                        const calc = fs.getFormulaireFromId(p.originNub.uid).calculatorName;
-                        const varName = fs.expandVariableName(p.originNub.calcType, p.symbol);
-                        const label = `${p.symbol} - ${varName} (${calc})`;
-                        this.addEntry(new SelectEntry(this._entriesBaseId + p.getParentComputeNode(false).uid + "_" + p.symbol, p, decodeHtml(label)));
-                    }
-                }
-                break;
-
-            case "verificateur_target": // Vérificateur, passe cible (à vérifier)
-                // find all Nubs of type FishPass
-                candidateNubs = Session.getInstance().getAllNubs().filter((element) => {
-                    return (
-                        (element instanceof FishPass)
-                        && element.calcType !== CalculatorType.Par // ParSimulation extends Par @TODO find something better
-                    );
-                });
-                for (const cn of candidateNubs) {
-                    const nub = fs.getFormulaireFromId(cn.uid);
-                    if (nub) {
-                        const label = nub.calculatorName + " (" + fs.getLocalisedTitleFromCalculatorType(nub.calculatorType) + ")";
-                        this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label)));
-                    } else {
-                        // silent fail, this Verificateur nub was probably loaded before all the candidate nubs are done loading
-                    }
-                }
-                break;
-
-            case "verificateur_species":
-                // add UIDs of all Espece type Nubs in the session
-                const especeNubs = Session.getInstance().getAllNubs().filter((element) => element.calcType === CalculatorType.Espece);
-                for (const en of especeNubs) {
-                    const form = ServiceFactory.formulaireService.getFormulaireFromNubId(en.uid);
-                    this.addEntry(
-                        new SelectEntry(
-                            this._entriesBaseId + en.uid,
-                            en.uid,
-                            sprintf(
-                                ServiceFactory.i18nService.localizeText("INFO_VERIFICATEUR_CUSTOM_SPECIES"),
-                                form ? form.calculatorName : "*** form not loaded yet ***"
-                            )
-                        )
-                    );
-                }
-                // add all FishSpecies
-                for (let j = 1; j < Object.keys(FishSpecies).length / 2; j++) { // exclude "0" (SPECIES_CUSTOM)
-                    const spgId = FishSpecies[j].substring(FishSpecies[j].lastIndexOf("_") + 1);
-                    this.addEntry(
-                        new SelectEntry(
-                            this._entriesBaseId + spgId,
-                            FishSpecies[j],
-                            ServiceFactory.i18nService.localizeText("INFO_ENUM_" + FishSpecies[j])
-                        )
-                    );
-                }
-                break;
-
-            case "upstream_basin": // PbCloisons, bassin amont
-                const pbWallU = this.parentForm.currentNub as PbCloison;
-                const preBarrageU = pbWallU.parent as PreBarrage;
-                const posDb = pbWallU.bassinAval?.findPositionInParent();
-                // river upstream
-                this.addEntry(
-                    new SelectEntry(
-                        this._entriesBaseId + "none",
-                        undefined,
-                        ServiceFactory.i18nService.localizeText("INFO_LIB_AMONT")
-                    )
-                );
-                // all available basins, depending on current downstream basin
-                for (const b of preBarrageU.bassins) {
-                    const pos = b.findPositionInParent();
-                    if (posDb === undefined || pos < posDb) {
-                        this.addEntry(
-                            new SelectEntry(
-                                this._entriesBaseId + b.uid,
-                                b.uid,
-                                ServiceFactory.i18nService.localizeMessage(b.description)
-                            )
-                        );
-                    }
-                }
-                break;
-
-            case "downstream_basin": // PbCloisons, bassin aval
-                const pbWallD = this.parentForm.currentNub as PbCloison;
-                const preBarrageD = pbWallD.parent as PreBarrage;
-                const posUb = pbWallD.bassinAmont?.findPositionInParent();
-                // all available basins, depending on current upstream basin
-                for (const b of preBarrageD.bassins) {
-                    const pos = b.findPositionInParent();
-                    if (posUb === undefined || pos > posUb) {
-                        this.addEntry(
-                            new SelectEntry(
-                                this._entriesBaseId + b.uid,
-                                b.uid,
-                                ServiceFactory.i18nService.localizeMessage(b.description)
-                            )
-                        );
-                    }
-                }
-                // river downstream
-                this.addEntry(
-                    new SelectEntry(
-                        this._entriesBaseId + "none",
-                        undefined,
-                        ServiceFactory.i18nService.localizeText("INFO_LIB_AVAL")
-                    )
-                );
-                break;
-        }
-    }
-
-    protected setDefaultValue() {
-        // default to first available entry if any
-        if (this._entries.length > 0) {
-            if (this._multiple) {
-                this.setValue([this._entries[0]]);
-            } else {
-                this.setValue(this._entries[0]);
-            }
-        } else {
-            // notify observers that no value is selected anymore
-            this.notifyValueChanged();
-        }
-    }
-
-    /**
-     * Once config is parsed, init original value from model
-     * (needs config, for this._entriesBaseId to be set)
-     */
-    protected afterParseConfig() {
-        this.populate();
-        this.initSelectedValue();
-    }
-
-    /**
-     * Reloads available entries, trying to keep the current selected
-     * value; does not notify observers if value did not change
-     */
-    public updateEntries() {
-        // store previous selected entry
-        const pse = this._selectedEntry;
-        // empty
-        this.clearEntries();
-        // populate
-        this.populate();
-        // if no entry is available anymore, unset value
-        if (this.entries.length === 0) {
-            if (this.multiple) {
-                super.setValue([]);
-            } else {
-                super.setValue(undefined);
-            }
-        } else {
-            // keep previously selected entry(ies) if possible
-            if (pse) {
-                if (!Array.isArray(pse) && pse.id) {
-                    this.setValueFromId(pse.id);
-                } else if (Array.isArray(pse) && pse.length > 0) {
-                    this.setValueFromId(pse.map((e) => e.id));
-                } else {
-                    this.setDefaultValue();
-                }
-            } else {
-                this.setDefaultValue();
-            }
-        }
-    }
-
-    /**
-     * Updates selectedValue; notifies observers only if
-     * value.id has changed
-     */
-    public setValue(v: SelectEntry | SelectEntry[]) {
-        const previousSelectedEntry = this._selectedEntry;
-        this._selectedEntry = v;
-        // if value changed
-        const valueChanged = (
-            !previousSelectedEntry
-            || (
-                !Array.isArray(previousSelectedEntry)
-                && !Array.isArray(v)
-                && previousSelectedEntry.id !== v.id
-            )
-            || (
-                Array.isArray(previousSelectedEntry)
-                && Array.isArray(v)
-                && !arraysAreEqual(previousSelectedEntry, v, "id", true)
-            )
-        );
-        if (valueChanged) {
-            this.notifyValueChanged();
-        }
-    }
-
-    /**
-     * Sets value from given ID(s); if it was not found, sets the
-     * first available entry as selectedValue
-     */
-    public setValueFromId(id: string | string[]) {
-        let found = false;
-        const entries = [];
-        if (this._multiple && Array.isArray(id)) {
-            for (const e of this._entries) {
-                if (id.includes(e.id)) {
-                    entries.push(e);
-                    found = true;
-                }
-            }
-            this.setValue(entries);
-        } else {
-            for (const e of this._entries) {
-                if (e.id === id) {
-                    found = true;
-                    this.setValue(e);
-                }
-            }
-        }
-        if (!found) {
-            this.setDefaultValue();
-        }
-    }
-
-}
diff --git a/src/app/formulaire/elements/select-field.ts b/src/app/formulaire/elements/select-field.ts
deleted file mode 100644
index ce08ddefd7113cfecbc06ee295df3ad6e86e405b..0000000000000000000000000000000000000000
--- a/src/app/formulaire/elements/select-field.ts
+++ /dev/null
@@ -1,244 +0,0 @@
-import {
-    CourbeRemous,
-    Nub,
-    ParallelStructure,
-    StructureType,
-    LoiDebit,
-    Session,
-    Solveur,
-    StructureProperties
- } from "jalhyd";
-
-import { Field } from "./field";
-import { SelectEntry } from "./select-entry";
-import { FormulaireNode } from "./formulaire-node";
-import { FormulaireDefinition } from "../definition/form-definition";
-import { ServiceFactory } from "../../services/service-factory";
-
-export class SelectField extends Field {
-
-    /** string to build the select entries IDs from */
-    protected _entriesBaseId: string;
-
-    protected _entries: SelectEntry[];
-
-    protected _selectedEntry: SelectEntry | SelectEntry[];
-
-    /** name of the Nub property associated to this field, if any */
-    protected _associatedProperty: string;
-
-    /** default value for this field */
-    protected _defaultValue: string;
-
-    /** if true, user can select multiple values */
-    protected _multiple = false;
-
-    /** if true, select box is grayed out */
-    public disabled = false;
-
-    /** source identifier for populating with available values */
-    protected source: string;
-
-    /**
-     * message to display below the select field when no option is selected,
-     * if this message is defined and not empty
-     */
-    protected _messageWhenEmpty: string;
-
-    constructor(parent: FormulaireNode) {
-        super(parent);
-        this.clearEntries();
-    }
-
-    public get entriesBaseId(): string {
-        return this._entriesBaseId;
-    }
-
-    public get entries() {
-        return this._entries;
-    }
-
-    public get associatedProperty(): string {
-        return this._associatedProperty;
-    }
-
-    public get defaultValue(): string {
-        return this._defaultValue;
-    }
-
-    public get multiple(): boolean {
-        return this._multiple;
-    }
-
-    public get messageWhenEmpty(): string {
-        let msg: string;
-        if (this._selectedEntry === undefined && this._messageWhenEmpty) {
-            msg = ServiceFactory.i18nService.localizeText(this._messageWhenEmpty);
-        }
-        return msg;
-    }
-
-    public clearEntries() {
-        this._entries = [];
-    }
-
-    public addEntry(e: SelectEntry) {
-        this._entries.push(e);
-        if (! this._selectedEntry) {
-            if (this._multiple) {
-                this.setValue([ e ]);
-            } else {
-                this.setValue(e);
-            }
-        }
-    }
-
-    /**
-     * Triggered at the end of parseConfig()
-     */
-    protected afterParseConfig() { }
-
-    public getEntryFromValue(val: any): SelectEntry {
-        for (const se of this._entries) {
-            if (se.value === val) {
-                return se;
-            }
-        }
-    }
-
-    public getValue(): SelectEntry | SelectEntry[] {
-        return this._selectedEntry;
-    }
-
-    public setValue(v: SelectEntry | SelectEntry[]) {
-        if (this._selectedEntry !== v) {
-            this._selectedEntry = v;
-            this.notifyValueChanged();
-        }
-    }
-
-    public notifyValueChanged() {
-        this.notifyObservers({
-            "action": "select",
-            "value": this._selectedEntry
-        }, this);
-    }
-
-    public updateLocalisation() {
-        super.updateLocalisation();
-        for (const e of this._entries) {
-            if (this.source === "solveur_targetted_result") {
-                // @WARNING clodo hack for Solveur
-                // 1. calculated param
-                const nub: Nub = (this.parentForm as FormulaireDefinition).currentNub;
-                const ntc = (nub as Solveur).nubToCalculate;
-                if (e.value !== undefined && ntc !== undefined) {
-                    if (e.value === "" && ntc.calculatedParam !== undefined) {
-                        const varName = ServiceFactory.formulaireService.expandVariableName(ntc.calcType, ntc.calculatedParam.symbol);
-                        e.label = `${varName} (${ntc.calculatedParam.symbol})`;
-                    } else {
-                        // 2. extra results
-                        const varName = ServiceFactory.formulaireService.expandVariableName(ntc.calcType, e.value);
-                        e.label = `${varName} (${e.value})`;
-                    }
-                }
-            } else {
-                // general case
-                const aId = e.id.split("_");
-                const trad = ServiceFactory.formulaireService.localizeText(
-                    `${aId[1].toUpperCase()}_${aId[2]}`,
-                    this.parentForm.currentNub.calcType
-                );
-                e.label = trad;
-            }
-        }
-    }
-
-    public parseConfig(field: {}, data?: {}) {
-        this._confId = field["id"];
-        this._entriesBaseId = this._confId + "_";
-        this._helpLink = field["help"];
-        this._associatedProperty = field["property"];
-        this._defaultValue = field["default"];
-        this._messageWhenEmpty = field["messageWhenEmpty"];
-        if (field["multiple"] !== undefined) {
-            this._multiple = field["multiple"];
-        }
-        this.source = field["source"];
-
-        this.loadEntriesFromSource();
-
-        this.afterParseConfig();
-    }
-
-    /**
-     * Adds available entries to the selector, depending on the "source" identifier
-     */
-    protected loadEntriesFromSource() {
-        const nub: Nub = (this.parentForm as FormulaireDefinition).currentNub;
-        // ad-hoc cases
-        switch (this.source) {
-            // driven by string[], not enum (easier for variable names)
-            case "remous_target":
-                this.addEntry(new SelectEntry(this._entriesBaseId + "none", ""));
-                for (const at of CourbeRemous.availableTargets) {
-                    const e: SelectEntry = new SelectEntry(this._entriesBaseId + at, at);
-                    this.addEntry(e);
-                }
-                break;
-
-            // driven by string[], not enum
-            case "solveur_targetted_result":
-                // @WARNING for localisation, @see hack in this.updateLocalisation()
-                // 1. calculated param
-                const ntc = (nub as Solveur).nubToCalculate;
-                if (ntc?.calculatedParam !== undefined) { // some nubs have no calculatedParam, for ex. SectionParam
-                    this.addEntry(new SelectEntry(this._entriesBaseId + "none", ""));
-                }
-                // 2. extra results
-                if (ntc?.resultsFamilies !== undefined) {
-                    for (const er of Object.keys(ntc.resultsFamilies)) {
-                        const e: SelectEntry = new SelectEntry(this._entriesBaseId + er, er);
-                        this.addEntry(e);
-                    }
-                }
-                break;
-
-            // possible values depend on CalcType
-            case "device_structure_type":
-                for (const st in (nub as ParallelStructure).getLoisAdmissibles()) {
-                    const e: SelectEntry = new SelectEntry(this._entriesBaseId + st, StructureType[st]);
-                    this.addEntry(e);
-                }
-                break;
-
-            // possible values depend on CalcType
-            case "device_loi_debit":
-                // get current structure type from appropriate Nub child
-                const child = nub.getChildren()[this.parent.indexAsKid()];
-                const la = (nub as ParallelStructure).getLoisAdmissibles();
-                const loiDebit = child.properties.getPropValue("loiDebit");
-                const stCode = StructureProperties.findCompatibleStructure(loiDebit, nub as ParallelStructure);
-                const stName = StructureType[stCode];
-                if (la[stName] !== undefined) {
-                    for (const ld of la[stName]) {
-                        const e: SelectEntry = new SelectEntry(this._entriesBaseId + LoiDebit[ld], ld);
-                        this.addEntry(e);
-                    }
-                }
-                break;
-
-            // general case : property values taken from an enum
-            default:
-                // find enum associated to property
-                const enumClass = Session.enumFromProperty[this._associatedProperty];
-                if (enumClass !== undefined) {
-                    // add one select entry per enum entry, in the enum order
-                    for (let j = 0; j < Object.keys(enumClass).length / 2; j++) {
-                        this.addEntry(new SelectEntry(this._entriesBaseId + j, j));
-                    }
-                }
-        }
-    }
-
-}
diff --git a/src/app/formulaire/elements/select-entry.ts b/src/app/formulaire/elements/select/select-entry.ts
similarity index 100%
rename from src/app/formulaire/elements/select-entry.ts
rename to src/app/formulaire/elements/select/select-entry.ts
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
new file mode 100644
index 0000000000000000000000000000000000000000..15194174f06e90276c5f50937ec06e04c7d1c70e
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-device-loi-debit.ts
@@ -0,0 +1,42 @@
+import { LoiDebit, ParallelStructure, StructureProperties, StructureType } from "jalhyd";
+import { SelectField } from "./select-field";
+import { SelectEntry } from "./select-entry";
+
+/*
+    "id": "select_loidebit",
+    "type": "select",
+    "property": "loiDebit",
+    "source": "device_loi_debit",
+    "help": {
+*/
+
+export class SelectFieldDeviceLoiDebit extends SelectField {
+    protected populate() {
+        // possible values depend on CalcType
+
+        // get current structure type from appropriate Nub child
+        const child = this.nub.getChildren()[this.parent.indexAsKid()];
+        const la = (this.nub as ParallelStructure).getLoisAdmissibles();
+        const loiDebit = child.properties.getPropValue("loiDebit");
+        const stCode = StructureProperties.findCompatibleStructure(loiDebit, this.nub as ParallelStructure);
+        const stName = StructureType[stCode];
+        if (la[stName] !== undefined) {
+            for (const ld of la[stName]) {
+                const e: SelectEntry = new SelectEntry(this._entriesBaseId + LoiDebit[ld], ld);
+                this.addEntry(e);
+            }
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..b818eedf5f26096a46a26a966c62884aa7cbd099
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-device-structure-type.ts
@@ -0,0 +1,32 @@
+import { ParallelStructure, StructureType } from "jalhyd";
+import { SelectField } from "./select-field";
+import { SelectEntry } from "./select-entry";
+
+/*
+    "id": "select_structure",
+    "type": "select",
+    "property": "structureType",
+    "source": "device_structure_type"
+*/
+
+export class SelectFieldDeviceStructureType extends SelectField {
+    protected populate() {
+        // possible values depend on CalcType
+        for (const st in (this.nub as ParallelStructure).getLoisAdmissibles()) {
+            const e: SelectEntry = new SelectEntry(this._entriesBaseId + st, StructureType[st]);
+            this.addEntry(e);
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..77fcab4bd494f04fe63923c1351db73f93935185
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-downstream-basin.ts
@@ -0,0 +1,53 @@
+import { ServiceFactory } from "app/services/service-factory";
+import { PbCloison, PreBarrage } from "jalhyd";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+/*
+    "id": "select_downstream_basin",
+    "type": "select_custom",
+    "source": "downstream_basin"
+*/    
+
+// PbCloisons, bassin aval
+export class SelectFieldDownstreamBasin extends SelectField {
+    protected populate() {
+        const pbWallD = this.parentForm.currentNub as PbCloison;
+        const preBarrageD = pbWallD.parent as PreBarrage;
+        const posUb = pbWallD.bassinAmont?.findPositionInParent();
+        // all available basins, depending on current upstream basin
+        for (const b of preBarrageD.bassins) {
+            const pos = b.findPositionInParent();
+            if (posUb === undefined || pos > posUb) {
+                this.addEntry(
+                    new SelectEntry(
+                        this._entriesBaseId + b.uid,
+                        b.uid,
+                        ServiceFactory.i18nService.localizeMessage(b.description)
+                    )
+                );
+            }
+        }
+        // river downstream
+        this.addEntry(
+            new SelectEntry(
+                this._entriesBaseId + "none",
+                undefined,
+                ServiceFactory.i18nService.localizeText("INFO_LIB_AVAL")
+            )
+        );
+    }
+
+    protected initSelectedValue() {
+        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-factory.ts b/src/app/formulaire/elements/select/select-field-factory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..38e8e7b49dda4cebca3d4a093252b911d0c34b4f
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-factory.ts
@@ -0,0 +1,66 @@
+import { FormulaireNode } from "../formulaire-node";
+import { SelectField } from "./select-field";
+import { SelectFieldDeviceLoiDebit } from "./select-field-device-loi-debit";
+import { SelectFieldDeviceStructureType } from "./select-field-device-structure-type";
+import { SelectFieldRemousTarget } from "./select-field-remous-target";
+import { SelectFieldSolverTargetedResult } from "./select-field-solver-targeted-result";
+import { SelectFieldUpstreamBasin } from "./select-field-upstream-basin";
+import { SelectFieldDownstreamBasin } from "./select-field-downstream-basin";
+import { SelectFieldSolverTarget } from "./select-field-solveur-target";
+import { SelectFieldSearchedParam } from "./select-field-searched-param";
+import { SelectFieldSpeciesList } from "./select-field-species-list";
+import { SelectFieldTargetPass } from "./select-field-target-pass";
+import { SelectFieldNubProperty } from "./select-field-nub-prop";
+
+export class SelectFieldFactory {
+    public static newSelectField(json: {}, parent: FormulaireNode): SelectField {
+        switch (json["id"]) {
+            case "select_downstream_basin":
+                return new SelectFieldDownstreamBasin(parent);
+
+            case "select_loidebit":
+                return new SelectFieldDeviceLoiDebit(parent);
+
+            case "select_searched_param":
+                return new SelectFieldSearchedParam(parent);
+
+            case "select_species_list":
+                return new SelectFieldSpeciesList(parent);
+
+            case "select_structure":
+                return new SelectFieldDeviceStructureType(parent);
+
+            case "select_target":
+                return new SelectFieldRemousTarget(parent);
+
+            case "select_target_nub":
+                return new SelectFieldSolverTarget(parent);
+
+            case "select_target_pass":
+                return new SelectFieldTargetPass(parent);
+
+            case "select_target_result":
+                return new SelectFieldSolverTargetedResult(parent);
+
+            case "select_upstream_basin":
+                return new SelectFieldUpstreamBasin(parent);
+
+            case "select_divingjetsupported":
+            case "select_gridprofile":
+            case "select_gridtype":
+            case "select_material":
+            case "select_operation":
+            case "select_partype":
+            case "select_passtype":
+            case "select_regime":
+            case "select_resolution":
+            case "select_section":
+            case "select_sppoperation":
+            case "select_unit":
+                return new SelectFieldNubProperty(parent, json);
+
+            default:
+                throw new Error("unknown select id ${id}");
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/app/formulaire/elements/select/select-field-nub-prop.ts b/src/app/formulaire/elements/select/select-field-nub-prop.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eca0463b303ed9766f0dad6d2121d807735b957f
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-nub-prop.ts
@@ -0,0 +1,38 @@
+import { Session } from "jalhyd";
+import { FormulaireNode } from "../formulaire-node";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+/*
+  par exemple :
+    "id": "select_regime",
+    "type": "select",
+    "property": "regime",
+    "default": "Fluvial"
+
+*/
+
+// nub property values taken from an enum
+// "standard" select that normally does not require customisation
+export class SelectFieldNubProperty extends SelectField {
+    constructor(parent: FormulaireNode, json: {}) {
+        super(parent);
+        this._associatedProperty = json["property"];
+        this._configDefaultValue = json["default"];
+    }
+
+    protected populate() {
+        // find enum associated to property
+        const enumClass = Session.enumFromProperty[this._associatedProperty];
+        if (enumClass !== undefined) {
+            // add one select entry per enum entry, in the enum order
+            for (let j = 0; j < Object.keys(enumClass).length / 2; j++) {
+                this.addEntry(new SelectEntry(this._entriesBaseId + j, j));
+            }
+        }
+    }
+
+    protected initSelectedValue() {
+        this.findAndSetDefaultValue();
+    }
+}
\ No newline at end of file
diff --git a/src/app/formulaire/elements/select/select-field-remous-target.ts b/src/app/formulaire/elements/select/select-field-remous-target.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d0f2c506da155a025ae889fc2e3ff2b8edcc445
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-remous-target.ts
@@ -0,0 +1,34 @@
+import { CourbeRemous } from "jalhyd";
+import { SelectField } from "./select-field";
+import { SelectEntry } from "./select-entry";
+
+/*
+    "id": "select_target",
+    "type": "select",
+    "property": "varCalc",
+    "source": "remous_target",
+    "help": {
+*/
+
+export class SelectFieldRemousTarget extends SelectField {
+    protected populate() {
+        // driven by string[], not enum (easier for variable names)
+        this.addEntry(new SelectEntry(this._entriesBaseId + "none", ""));
+        for (const at of CourbeRemous.availableTargets) {
+            const e: SelectEntry = new SelectEntry(this._entriesBaseId + at, at);
+            this.addEntry(e);
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..5380e12381c10bee69f4fd003597ef914fd12d9d
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-searched-param.ts
@@ -0,0 +1,63 @@
+import { ServiceFactory } from "app/services/service-factory";
+import { decodeHtml } from "app/util";
+import { acSection, Nub, Solveur } from "jalhyd";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+/*
+    "id": "select_searched_param",
+    "type": "select_custom",
+    "source": "solveur_searched"
+*/
+
+// Solveur, paramètre recherché (à faire varier)
+export class SelectFieldSearchedParam extends SelectField {
+    protected populate() {
+        const fs = ServiceFactory.formulaireService;
+
+        // find all non-calculated, non-linked parameters of all Nubs that
+        // the current "target" Nub depends on (if any)
+        const solv = this.parentForm.currentNub as Solveur;
+        const ntc: Nub = solv.nubToCalculate;
+        const searchableParams = Solveur.getDependingNubsSearchableParams(
+            ntc,
+            solv.targettedResult !== undefined && solv.targettedResult !== ""
+        );
+        for (const p of searchableParams) {
+            if (p.visible) {
+                const calc = fs.getFormulaireFromId(p.originNub.uid).calculatorName;
+                const varName = fs.expandVariableName(p.originNub.calcType, p.symbol);
+                const label = `${p.symbol} - ${varName} (${calc})`;
+                this.addEntry(new SelectEntry(this._entriesBaseId + p.getParentComputeNode(false).uid + "_" + p.symbol, p, decodeHtml(label)));
+            }
+        }
+    }
+
+    protected initSelectedValue() {
+        const sp = (this.nub as Solveur).searchedParameter;
+        if (sp !== undefined) {
+            let parentNubUid;
+            const parentNub = sp.getParentComputeNode(false);
+            if (parentNub instanceof acSection) {
+                parentNubUid = parentNub.uid;
+            }
+            else {
+                parentNubUid = sp.nubUid
+            }
+            this.setValueFromId(this._entriesBaseId + parentNubUid + "_" + sp.symbol);
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..2b10da8276479761487795781c4aecc734980237
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-solver-targeted-result.ts
@@ -0,0 +1,64 @@
+import { FormulaireDefinition } from "app/formulaire/definition/form-definition";
+import { ServiceFactory } from "app/services/service-factory";
+import { Nub, Solveur } from "jalhyd";
+import { FormulaireElement } from "../formulaire-element";
+import { SelectField } from "./select-field";
+import { SelectEntry } from "./select-entry";
+
+/*
+    "id": "select_target_result",
+    "type": "select",
+    "property": "targettedResult",
+    "source": "solveur_targetted_result",
+    "default": ""
+*/
+export class SelectFieldSolverTargetedResult extends SelectField {
+
+    protected populate() {
+        // @WARNING for localisation, @see hack in this.updateLocalisation()
+        // 1. calculated param
+        const ntc = (this.nub as Solveur).nubToCalculate;
+        if (ntc?.calculatedParam !== undefined) { // some nubs have no calculatedParam, for ex. SectionParam
+            this.addEntry(new SelectEntry(this._entriesBaseId + "none", ""));
+        }
+        // 2. extra results
+        if (ntc?.resultsFamilies !== undefined) {
+            for (const er of Object.keys(ntc.resultsFamilies)) {
+                const e: SelectEntry = new SelectEntry(this._entriesBaseId + er, er);
+                this.addEntry(e);
+            }
+        }
+    }
+
+    protected initSelectedValue() {
+        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) {
+            // @WARNING clodo hack for Solveur
+            // 1. calculated param
+            const nub: Nub = (this.parentForm as FormulaireDefinition).currentNub;
+            const ntc = (nub as Solveur).nubToCalculate;
+            if (e.value !== undefined && ntc !== undefined) {
+                if (e.value === "" && ntc.calculatedParam !== undefined) {
+                    const varName = ServiceFactory.formulaireService.expandVariableName(ntc.calcType, ntc.calculatedParam.symbol);
+                    e.label = `${varName} (${ntc.calculatedParam.symbol})`;
+                } else {
+                    // 2. extra results
+                    const varName = ServiceFactory.formulaireService.expandVariableName(ntc.calcType, e.value);
+                    e.label = `${varName} (${e.value})`;
+                }
+            }
+        }
+    }
+}
\ 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
new file mode 100644
index 0000000000000000000000000000000000000000..64d37dc33d11647c5e44321f602e02396ff2ebb2
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-solveur-target.ts
@@ -0,0 +1,62 @@
+/*
+    "id": "select_target_nub",
+    "type": "select_custom",
+    "source": "solveur_target"
+*/
+
+import { ServiceFactory } from "app/services/service-factory";
+import { decodeHtml } from "../../../util";
+import { Session, Solveur } from "jalhyd";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+// Solveur, module cible (à calculer)
+export class SelectFieldSolverTarget extends SelectField {
+    protected populate() {
+
+        const fs = ServiceFactory.formulaireService;
+
+        // find all Nubs having at least one link to another Nub's result
+        const candidateNubs: any[] =
+            Session.getInstance().getDownstreamNubs().concat(
+                Session.getInstance().getUpstreamNubsHavingExtraResults()
+            ).filter(
+                (element, index, self) => self.findIndex((e) => e.uid === element.uid) === index
+            );
+        for (const cn of candidateNubs) {
+            const nub = fs.getFormulaireFromId(cn.uid);
+            if (nub) {
+                const calc = nub.calculatorName;
+                let label = calc;
+                // calculated param
+                if (cn.calculatedParam !== undefined) {
+                    const varName = fs.expandVariableName(cn.calcType, cn.calculatedParam.symbol);
+                    label += ` / ${varName} (${cn.calculatedParam.symbol})`;
+                }
+                this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label)));
+            } else {
+                // silent fail, this Solveur nub was probably loaded before all the candidate nubs are done loading
+            }
+        }
+    }
+
+    protected initSelectedValue() {
+        const ntc = (this.nub as Solveur).nubToCalculate;
+        if (ntc !== undefined) {
+            this.setValueFromId(this._entriesBaseId + ntc.uid);
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..bcdbbee79f373489d0900edc519eb78cec080c6a
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-species-list.ts
@@ -0,0 +1,73 @@
+/*
+"type": "select_custom",
+"id": "select_species_list",
+"source": "verificateur_species",
+"multiple": true
+*/
+
+import { ServiceFactory } from "app/services/service-factory";
+import { CalculatorType, FishSpecies, Session, Verificateur } from "jalhyd";
+import { sprintf } from "sprintf-js";
+import { FormulaireNode } from "../formulaire-node";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+// Vérificateur, liste d'espèces (choix multiple)
+export class SelectFieldSpeciesList extends SelectField {
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this._multiple = true;
+    }
+
+    protected populate() {
+        // add UIDs of all Espece type Nubs in the session
+        const especeNubs = Session.getInstance().getAllNubs().filter((element) => element.calcType === CalculatorType.Espece);
+        for (const en of especeNubs) {
+            const form = ServiceFactory.formulaireService.getFormulaireFromNubId(en.uid);
+            this.addEntry(
+                new SelectEntry(
+                    this._entriesBaseId + en.uid,
+                    en.uid,
+                    sprintf(
+                        ServiceFactory.i18nService.localizeText("INFO_VERIFICATEUR_CUSTOM_SPECIES"),
+                        form ? form.calculatorName : "*** form not loaded yet ***"
+                    )
+                )
+            );
+        }
+        // add all FishSpecies
+        for (let j = 1; j < Object.keys(FishSpecies).length / 2; j++) { // exclude "0" (SPECIES_CUSTOM)
+            const spgId = FishSpecies[j].substring(FishSpecies[j].lastIndexOf("_") + 1);
+            this.addEntry(
+                new SelectEntry(
+                    this._entriesBaseId + spgId,
+                    FishSpecies[j],
+                    ServiceFactory.i18nService.localizeText("INFO_ENUM_" + FishSpecies[j])
+                )
+            );
+        }
+    }
+
+    protected initSelectedValue() {
+        const sl = (this.nub as Verificateur).speciesList;
+        if (sl !== undefined) {
+            this.setValueFromId(sl.map((s) => {
+                const spgId = s.substring(s.lastIndexOf("_") + 1);
+                return this._entriesBaseId + spgId;
+            }));
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..36430d2179ee8d9b72741555f73003a123ce05f0
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-target-pass.ts
@@ -0,0 +1,62 @@
+import { ServiceFactory } from "app/services/service-factory";
+import { decodeHtml } from "app/util";
+import { CalculatorType, FishPass, Session, Verificateur } from "jalhyd";
+import { FormulaireElement } from "../formulaire-element";
+import { FormulaireNode } from "../formulaire-node";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+/*
+    "id": "select_target_pass",
+    "type": "select_custom",
+    "source": "verificateur_target",
+    "messageWhenEmpty": "INFO_VERIF_CREATE_PASS_FRIST"
+*/
+
+// Vérificateur, passe cible (à vérifier)
+export class SelectFieldTargetPass extends SelectField {
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this._messageWhenEmpty = "INFO_VERIF_CREATE_PASS_FRIST";
+    }
+
+    protected populate() {
+        const fs = ServiceFactory.formulaireService;
+        // find all Nubs of type FishPass
+        const candidateNubs: any[] = Session.getInstance().getAllNubs().filter((element) => {
+            return (
+                (element instanceof FishPass)
+                && element.calcType !== CalculatorType.Par // ParSimulation extends Par @TODO find something better
+            );
+        });
+        for (const cn of candidateNubs) {
+            const nub = fs.getFormulaireFromId(cn.uid);
+            if (nub) {
+                const label = nub.calculatorName + " (" + fs.getLocalisedTitleFromCalculatorType(nub.calculatorType) + ")";
+                this.addEntry(new SelectEntry(this._entriesBaseId + cn.uid, cn.uid, decodeHtml(label)));
+            } else {
+                // silent fail, this Verificateur nub was probably loaded before all the candidate nubs are done loading
+            }
+        }
+    }
+
+    protected initSelectedValue() {
+        const ntv = (this.nub as Verificateur).nubToVerify;
+        if (ntv !== undefined) {
+            this.setValueFromId(this._entriesBaseId + ntv.uid);
+        }
+    }
+
+    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
new file mode 100644
index 0000000000000000000000000000000000000000..06e335f5c6d0fdec4d6d03e70245ac1365995f58
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field-upstream-basin.ts
@@ -0,0 +1,53 @@
+import { ServiceFactory } from "app/services/service-factory";
+import { PbCloison, PreBarrage } from "jalhyd";
+import { SelectEntry } from "./select-entry";
+import { SelectField } from "./select-field";
+
+/*
+    "id": "select_upstream_basin",
+    "type": "select_custom",
+    "source": "upstream_basin"
+*/
+
+// PbCloisons, bassin amont
+export class SelectFieldUpstreamBasin extends SelectField {
+    protected populate() {
+        const pbWallU = this.parentForm.currentNub as PbCloison;
+        const preBarrageU = pbWallU.parent as PreBarrage;
+        const posDb = pbWallU.bassinAval?.findPositionInParent();
+        // river upstream
+        this.addEntry(
+            new SelectEntry(
+                this._entriesBaseId + "none",
+                undefined,
+                ServiceFactory.i18nService.localizeText("INFO_LIB_AMONT")
+            )
+        );
+        // all available basins, depending on current downstream basin
+        for (const b of preBarrageU.bassins) {
+            const pos = b.findPositionInParent();
+            if (posDb === undefined || pos < posDb) {
+                this.addEntry(
+                    new SelectEntry(
+                        this._entriesBaseId + b.uid,
+                        b.uid,
+                        ServiceFactory.i18nService.localizeMessage(b.description)
+                    )
+                );
+            }
+        }
+    }
+
+    protected initSelectedValue() {
+        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
new file mode 100644
index 0000000000000000000000000000000000000000..c6e2024ed5ea804d0ebb859d7055a93171a3f5d3
--- /dev/null
+++ b/src/app/formulaire/elements/select/select-field.ts
@@ -0,0 +1,268 @@
+import { Field } from "../field";
+import { SelectEntry } from "./select-entry";
+import { arraysAreEqual } from "../../../util";
+import { FormulaireNode } from "../formulaire-node";
+import { ServiceFactory } from "app/services/service-factory";
+import { FormulaireDefinition } from "../../definition/form-definition";
+import { Nub } from "jalhyd";
+
+export abstract class SelectField extends Field {
+
+    /**
+     * select options
+     */
+    protected _entries: SelectEntry[];
+
+    /**
+     * currently selected option
+     */
+    protected _selectedEntry: SelectEntry | SelectEntry[];
+
+    /** if true, user can select multiple values */
+    protected _multiple = false;
+
+    /** if true, select box is grayed out */
+    public disabled = false;
+
+    /** string to build the select entries IDs from */
+    protected _entriesBaseId: string;
+
+    /** name of the Nub property associated to this field, if any */
+    protected _associatedProperty: string;
+
+    /** default value (from configuration) for this field */
+    protected _configDefaultValue: string;
+
+    /**
+     * message to display below the select field when no option is selected,
+     * if this message is defined and not empty
+     */
+    protected _messageWhenEmpty: string;
+
+    constructor(parent: FormulaireNode) {
+        super(parent);
+        this.clearEntries();
+    }
+
+    /**
+     * associated nub
+     */
+    protected get nub(): Nub {
+        return (this.parentForm as FormulaireDefinition).currentNub;
+    }
+
+    public getValue(): SelectEntry | SelectEntry[] {
+        return this._selectedEntry;
+    }
+
+    /**
+     * Updates _selectedEntry; notifies observers only if
+     * value.id has changed
+     */
+    public setValue(v: SelectEntry | SelectEntry[]) {
+        // if multiple is true, value must be an array
+        if (this._multiple && !Array.isArray(v)) {
+            throw new Error("select value is not an array");
+        }
+
+        const previousSelectedEntry = this._selectedEntry;
+        this._selectedEntry = v;
+
+        // if old and new values are not both undefined
+        if (!(previousSelectedEntry === undefined && v === undefined)) {
+            // if value changed
+            const valueChanged = (
+                (previousSelectedEntry === undefined && v !== undefined)
+                || (
+                    !Array.isArray(previousSelectedEntry)
+                    && !Array.isArray(v)
+                    && previousSelectedEntry.id !== v.id
+                )
+                || (
+                    Array.isArray(previousSelectedEntry)
+                    && Array.isArray(v)
+                    && !arraysAreEqual(previousSelectedEntry, v, "id", true)
+                )
+            );
+            if (valueChanged) {
+                this.notifyValueChanged();
+            }
+        }
+    }
+
+    public notifyValueChanged() {
+        this.notifyObservers({
+            "action": "select",
+            "value": this._selectedEntry
+        }, this);
+    }
+
+    /**
+     * Sets value from given entry id(s); if it was not found, sets the
+     * first available entry as selectedValue
+     */
+    protected setValueFromId(id: string | string[]) {
+        let found = false;
+        const entries = [];
+        if (Array.isArray(id)) {
+            for (const e of this._entries) {
+                if (id.includes(e.id)) {
+                    entries.push(e);
+                    found = true;
+                }
+            }
+            this.setValue(entries);
+        } else {
+            for (const e of this._entries) {
+                if (e.id === id) {
+                    found = true;
+                    this.setValue(e);
+                }
+            }
+        }
+        if (!found) {
+            this.findAndSetDefaultValue();
+        }
+    }
+
+    /**
+     * try to find a default value to select
+     */
+    protected findAndSetDefaultValue() {
+        // default to first available entry if any
+        if (this._entries.length > 0) {
+            if (this._multiple) {
+                this.setValue([this._entries[0]]);
+            } else {
+                this.setValue(this._entries[0]);
+            }
+        } else {
+            // notify observers that no value is selected anymore
+            this.notifyValueChanged();
+        }
+    }
+
+    public parseConfig(field: {}, data?: {}) {
+        this._confId = field["id"];
+        this._entriesBaseId = this._confId + "_";
+        this._helpLink = field["help"];
+        this.afterParseConfig();
+    }
+
+    /**
+     * Once config is parsed, init original value from model
+     * (needs config for this._entriesBaseId to be set).
+     * Triggered at the end of parseConfig()
+     */
+    protected afterParseConfig() {
+        this.populate();
+        this.initSelectedValue();
+    }
+
+    /**
+     * fill select with options
+     */
+    protected abstract populate();
+
+    /**
+     * initialise select (loads UI with the value held by the model)
+     */
+    protected abstract initSelectedValue();
+
+    /**
+     * associated nub property
+     */
+    public get associatedProperty(): string {
+        return this._associatedProperty;
+    }
+
+    /**
+     * default value from configuration
+     */
+    public get configDefaultValue(): string {
+        return this._configDefaultValue;
+    }
+
+    private clearEntries() {
+        this._entries = [];
+    }
+
+    public get entries() {
+        return this._entries;
+    }
+
+    protected addEntry(e: SelectEntry) {
+        this._entries.push(e);
+    }
+
+    public getEntryFromValue(val: any): SelectEntry {
+        for (const se of this._entries) {
+            if (se.value === val) {
+                return se;
+            }
+        }
+    }
+
+    /**
+    * Reloads available entries, trying to keep the current selected
+    * value; does not notify observers if value did not change
+    */
+    public updateEntries() {
+        // store previous selected entry
+        const pse = this._selectedEntry;
+        // empty
+        this.clearEntries();
+        // populate
+        this.populate();
+        this.updateLocalisation();
+        // if no entry is available anymore, unset value
+        if (this._entries.length === 0) {
+            if (this._multiple) {
+                this.setValue([]);
+            } else {
+                this.setValue(undefined);
+            }
+        } else {
+            // keep previously selected entry(ies) if possible
+            if (pse) {
+                if (!Array.isArray(pse) && pse.id) {
+                    this.setValueFromId(pse.id);
+                } else if (Array.isArray(pse) && pse.length > 0) {
+                    this.setValueFromId(pse.map((e) => e.id));
+                } else {
+                    this.findAndSetDefaultValue();
+                }
+            } else {
+                this.findAndSetDefaultValue();
+            }
+        }
+    }
+
+    public get entriesBaseId(): string {
+        return this._entriesBaseId;
+    }
+
+    public get messageWhenEmpty(): string {
+        let msg: string;
+        if (this._selectedEntry === undefined && this._messageWhenEmpty) {
+            msg = ServiceFactory.i18nService.localizeText(this._messageWhenEmpty);
+        }
+        return msg;
+    }
+
+    public get multiple(): boolean {
+        return this._multiple;
+    }
+
+    public updateLocalisation() {
+        super.updateLocalisation();
+        for (const e of this._entries) {
+            const aId = e.id.split("_");
+            const trad = ServiceFactory.formulaireService.localizeText(
+                `${aId[1].toUpperCase()}_${aId[2]}`,
+                this.parentForm.currentNub.calcType
+            );
+            e.label = trad;
+        }
+    }
+}
diff --git a/src/app/services/formulaire.service.ts b/src/app/services/formulaire.service.ts
index 4c9e42baa9e5dc138d02427ff9d4d4ad1520bad8..83020d52734284438d807e65e6f402cb4fcc3127 100644
--- a/src/app/services/formulaire.service.ts
+++ b/src/app/services/formulaire.service.ts
@@ -32,7 +32,7 @@ import { NotificationsService } from "./notifications.service";
 import { FormulaireDefinition } from "../formulaire/definition/form-definition";
 import { FormulaireElement } from "../formulaire/elements/formulaire-element";
 import { InputField } from "../formulaire/elements/input-field";
-import { SelectField } from "../formulaire/elements/select-field";
+import { SelectField } from "../formulaire/elements/select/select-field";
 import { FormulaireSectionParametree } from "../formulaire/definition/form-section-parametree";
 import { FormulaireCourbeRemous } from "../formulaire/definition/form-courbe-remous";
 import { FormulaireParallelStructure } from "../formulaire/definition/form-parallel-structures";