diff --git a/src/app/calculators/parallel-structures/parallel-structures.config.json b/src/app/calculators/parallel-structures/parallel-structures.config.json
index 46de0359d1e8c02524f7f6144116d83bdbd1c0dc..3f1f91f918b8aadb17d7e93b2cc96ea6c13c9b70 100644
--- a/src/app/calculators/parallel-structures/parallel-structures.config.json
+++ b/src/app/calculators/parallel-structures/parallel-structures.config.json
@@ -79,6 +79,14 @@
             }
         ]
     },
+    {
+        "id": "struct_container",
+        "type": "template_container",
+        "templates": [
+            "fs_struct_cem88d",
+            "fs_struct_cem88v"
+        ]
+    },
     {
         "id": "fs_param_calc",
         "type": "fieldset",
diff --git a/src/app/formulaire/check-field.ts b/src/app/formulaire/check-field.ts
index 098e3abc6d9c756b8c935f18e3bd3bf814442eb3..84555e23c6a81ffce9a719229678b0e0753d7884 100644
--- a/src/app/formulaire/check-field.ts
+++ b/src/app/formulaire/check-field.ts
@@ -27,4 +27,10 @@ export class CheckField extends Field {
     public get isValid(): boolean {
         return true;
     }
+
+    public clone(): CheckField {
+        const res: CheckField = new CheckField(this.computeNodeType, this.id, this.formId);
+        res._value = this._value;
+        return res;
+    }
 }
diff --git a/src/app/formulaire/field.ts b/src/app/formulaire/field.ts
index 88bceabd7bd1dc070a627e7e3e2f81cedcb24226..57caa7f5c2757b8efa11ed36693ee6ac187c462e 100644
--- a/src/app/formulaire/field.ts
+++ b/src/app/formulaire/field.ts
@@ -27,4 +27,6 @@ export abstract class Field extends FormulaireElement {
 
     public abstract getValue(): any;
     public abstract setValue(val: any): void;
+
+    public abstract clone(): Field;
 }
diff --git a/src/app/formulaire/fieldset-container.ts b/src/app/formulaire/fieldset-container.ts
new file mode 100644
index 0000000000000000000000000000000000000000..95ed4452f37dc360daa2a9ce888020f7d726546e
--- /dev/null
+++ b/src/app/formulaire/fieldset-container.ts
@@ -0,0 +1,58 @@
+import { ComputeNodeType } from "jalhyd";
+
+import { FormulaireElement } from "./formulaire-element";
+import { FieldSet } from "./fieldset";
+import { Dependency } from "./dependency";
+
+export class FieldsetContainer extends FormulaireElement {
+    private _templates: FieldSet[];
+
+    private _fieldsets: FieldSet[];
+
+    constructor(id: string, formId: number) {
+        super(ComputeNodeType.None, id, formId);
+        this._fieldsets = [];
+        this._templates = [];
+    }
+
+    private checkTemplate(fs: FieldSet) {
+        if (!fs.isTemplate)
+            throw new Error(`le Fieldset ${fs.id} n'est pas un template`);
+    }
+
+    public addTemplate(fs: FieldSet) {
+        if (this.hasTemplate(fs))
+            console.log(`Warning : le Fieldset template ${fs.id} a déjà été ajouté`);
+        else
+            this._templates.push(fs);
+    }
+
+    private hasTemplate(fs: FieldSet): boolean {
+        this.checkTemplate(fs);
+
+        for (const f of this._templates)
+            if (f.id === fs.id)
+                return true;
+        return false;
+    }
+
+    private getTemplate(id: string) {
+        for (const f of this._templates)
+            if (f.id === id)
+                return f;
+        return undefined;
+    }
+
+    public addFromTemplate(templId: string) {
+        const templ: FieldSet = this.getTemplate(templId);
+        this._templates.push(templ.instanciateTemplate());
+    }
+
+    public get fieldsets(): FieldSet[] {
+        return this._fieldsets;
+    }
+
+    protected verifyDependency(d: Dependency): boolean {
+        return true;
+    }
+}
diff --git a/src/app/formulaire/fieldset.ts b/src/app/formulaire/fieldset.ts
index 5b007db69f72f12e97fc0046027a3d084b0b0d87..96fd60491e6396ce8bb0fb41aa6511bc81a803cd 100644
--- a/src/app/formulaire/fieldset.ts
+++ b/src/app/formulaire/fieldset.ts
@@ -26,6 +26,13 @@ export class FieldSet extends FormulaireElement {
         return this._template;
     }
 
+    public instanciateTemplate(): FieldSet {
+        const res = new FieldSet(this.computeNodeType, this.id, this.formId, false);
+        for (const f of this._fields)
+            res.addField(f.clone());
+        return res;
+    }
+
     public addField(f: Field) {
         this._fields.push(f);
     }
diff --git a/src/app/formulaire/formulaire-definition.ts b/src/app/formulaire/formulaire-definition.ts
index 1b37b5c43d8434490d785294446b20503a2ee3de..f0afd4b776a17faec0447e579743f1022061972f 100644
--- a/src/app/formulaire/formulaire-definition.ts
+++ b/src/app/formulaire/formulaire-definition.ts
@@ -14,6 +14,7 @@ import { CheckField } from "./check-field";
 import { SelectField } from "./select-field";
 import { SelectEntry } from "./select-entry";
 import { FieldSet } from "./fieldset";
+import { FieldsetContainer } from "./fieldset-container";
 import { Dependency } from "./dependency";
 import { DependencyCondition, DependencyConditionType } from "./dependency-condition";
 import { FormulaireElement } from "./formulaire-element";
@@ -40,6 +41,8 @@ export class FormulaireDefinition extends Observable implements Observer {
 
     private _fieldSets: FieldSet[] = [];
 
+    private _fieldsetContainer: FieldsetContainer;
+
     private _dependencies: Dependency[] = [];
 
     /**
@@ -543,6 +546,15 @@ export class FormulaireDefinition extends Observable implements Observer {
         this.parse_dependencies(res, json);
     }
 
+    private parse_template_container(json: {}) {
+        const fsc_id: string = json["id"];
+
+        this._fieldsetContainer = new FieldsetContainer(fsc_id, this._uid);
+        const templs: string[] = json["templates"];
+        for (const t of templs)
+            this._fieldsetContainer.addTemplate(this.getFieldSet(t));
+    }
+
     private getOption(option: string): string {
         for (let conf_index in this._config) {
             let conf = this._config[conf_index];
@@ -584,6 +596,10 @@ export class FormulaireDefinition extends Observable implements Observer {
                     this._sectionSelectFieldId = this.getOption("sectionSelectId");
                     break;
 
+                case "template_container":
+                    this.parse_template_container(conf);
+                    break;
+
                 default:
                     throw new Error(`type d'objet de calculette ${type} non pris en charge`);
             }
diff --git a/src/app/formulaire/ngparam.ts b/src/app/formulaire/ngparam.ts
index 7556284a40a143904966a9df781b60ca52e5a76d..0e394d02dd3b4ee700f9b2512acc801e7f63ab3a 100644
--- a/src/app/formulaire/ngparam.ts
+++ b/src/app/formulaire/ngparam.ts
@@ -284,6 +284,20 @@ export class NgParameter extends InputField implements IObservable {
         }
     }
 
+    public clone(): NgParameter {
+        const res: NgParameter = new NgParameter(this._paramDef.clone(), this.formId);
+        res.unit = this.unit;
+        res.radioConfig = this.radioConfig;
+        res.radioState = this.radioState;
+        res.isDefault = this.isDefault;
+        res._valueMode = this.valueMode;
+        res._minValue = this._minValue;
+        res._maxValue = this._maxValue;
+        res._stepValue = this._stepValue;
+        res._valueList = this._valueList.slice(0); // copîe
+        return res;
+    }
+
     // interface IObservable
 
     /**
diff --git a/src/app/formulaire/select-field.ts b/src/app/formulaire/select-field.ts
index 1887cd574c071a7223fabb7c82b207d3ecd63c2c..a81404b11fff15d2f7963cd7e14ccbc7d34a1c2f 100644
--- a/src/app/formulaire/select-field.ts
+++ b/src/app/formulaire/select-field.ts
@@ -73,6 +73,14 @@ export class SelectField extends Field implements IObservable {
         }
     }
 
+    public clone(): SelectField {
+        const res: SelectField = new SelectField(this.computeNodeType, this.id, this.formId);
+        for (const e of this._entries)
+            res.addEntry(e);
+
+        return res;
+    }
+
     // interface IObservable
 
     /**