Bonjour !

Je bloque sur un problème de `CollectionType`. J'ai un formulaire qui sert à créer des membres de famille. Chaque membre de famille peut avoir un certain nombre d'adresses et un certain nombre de moyens de contact. J'ai donc deux `CollectionType` dans un `CollectionType`.
Mon formulaire de départ :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('childsFamily', CollectionType::class, array(
            'entry_type' => RelationshipType::class,
            'allow_add' => true,
            'prototype' => true,
            'attr' => array('class' => 'child-family')
        ));
    }
 
    public function getBlockPrefix()
    {
        return 'AddChildStep3';
    }
Dont le RelationshipType ressemble à ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
 public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('relRole', EntityType::class, array(
                'class' => 'VSCrmBundle:RelRole'
            ))
            //->add('sourceId', PersonChildType::class)
            ->add('destinationId', PersonRelationshipType::class, array(
                'block_name' => 'destination_id',
                'label' => 'Responsible'
            ));
    }
Et la le destinationId qui est un PersonRelationshipType qui est :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName')
            ->add('lastName')
            ->add('bornOn', BirthdayType::class, array(
                'required' => false
            ))
            ->add('familySituation', ChoiceType::class, array(
                'choices' => array(
                    'Single' => 'SINGLE',
                    'Married' => 'MARRIED',
                    'Other' => 'OTHER'
                )
            ))
            ->add('profession')
            ->add('addresses', CollectionType::class, array(
                'entry_type' => AddressType::class,
                'allow_add' => true,
                'allow_delete' => true
            ))
            ->add('medias', CollectionType::class, array(
                'entry_type' => MediaType::class,
                'allow_add' => true,
                'allow_delete' => true
            ));
    }
Chaque membre de famille est ajouté grâce à une fonction jQuery qui nous vient tout droit de la documentation :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
var familyCollectionHolder;
 
// Set up an "add address" link
var addFMemberLink = $('<a href="#" class="add_fmember_link">Add family member</a>');
var newFamilyLinkP = $('<p class="centered"></p>').append(addFMemberLink);
 
function addFmemberForm(familyCollectionHolder, newFamilyLinkP){
    // Get the data prototype
    var prototype = familyCollectionHolder.data('prototype');
 
    // get the new index
    var index = familyCollectionHolder.data('index');
 
    // Replace '__name__' in the prototype's HTML
    //instead be a number based on how many items we have
    var newForm = prototype.replace(/__name__/g, index);
 
    // Increase the index with one for the new item
    familyCollectionHolder.data('index', index+1);
 
    //Display the form in the page nan li, before the "add address" link
    var newFormP = $('<div class="one-fmember"></div>').append(newForm);
    newFamilyLinkP.before(newFormP);
    addFMemberDeleteLink(newFormP);
}
 
function addFMemberDeleteLink(fmemberFormP)
{
    var removeFormP = $('<p class="centered"><a href="#" style="color:red">Delete member</a></p>');
    fmemberFormP.append(removeFormP);
    removeFormP.on('click', function(e){
         e.preventDefault();
         fmemberFormP.remove();
    })
}
 
function handleFcData(familyCollectionHolder,newFamilyLinkP)
{
    // Get the div that holds the collection of addresses
    familyCollectionHolder = $('div#familyMembersList');
    // add a delete link to all of the existensing forms
    familyCollectionHolder.find('div.one-fmember').each(function(){
        addFMemberDeleteLink($(this));
    });
    // add the "add address" anchor
    familyCollectionHolder.append(newFamilyLinkP);
    // Count the current form inputs
    // use that as the new index when inserting a new item
    familyCollectionHolder.data('index', familyCollectionHolder.find(':input').length);
 
    return familyCollectionHolder;
}
 
jQuery(document).ready(function(){
 
    familyCollectionHolder = handleFcData(familyCollectionHolder, newFamilyLinkP);
 
    addFMemberLink.on('click',function(e)
    {
        // Prevent the link from creating a "#" on the URL
        e.preventDefault();
        // add a new address form
        addFmemberForm(familyCollectionHolder, newFamilyLinkP);
    })
});
J'ai donc un code HTML de la sorte :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
<div class="row">
                <p class="centered spaced">Define child's family</p>
            </div>
 
            <div class="row">
                <div id="familyMembersList" data-prototype="{{ form_widget(form.childsFamily.vars.prototype)|e('html_attr') }}">
                </div>
            </div>
J'ai fait un `entry_widget` customisé qui fait en sorte à ce que à chaque fois qu'un membre de famille est ajouté, je met ça parfaitement en forme et j'ajoute mes deux autres collections :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{% block _AddChildStep3_childsFamily_entry_widget %}
    <div class="row">
        <div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_label(form.relRole, "", {'label_attr': {'class': 'pull-right'}}) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_widget(form.relRole) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_errors(form.relRole) -}}
            </div>
        </div>
 
        <br/>
 
        <div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_label(form.destinationId.firstName, "", {'label_attr': {'class': 'pull-right'}}) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_widget(form.destinationId.firstName) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_errors(form.destinationId.firstName) -}}
            </div>
        </div>
 
        <br/>
 
        <div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_label(form.destinationId.lastName, "", {'label_attr': {'class': 'pull-right'}}) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_widget(form.destinationId.lastName) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_errors(form.destinationId.lastName) -}}
            </div>
        </div>
 
        <br/>
 
        <div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_label(form.destinationId.bornOn, "", {'label_attr': {'class': 'pull-right'}}) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_widget(form.destinationId.bornOn) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_errors(form.destinationId.bornOn) -}}
            </div>
        </div>
 
        <br/>
 
        <div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}">
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_label(form.destinationId.profession, "", {'label_attr': {'class': 'pull-right'}}) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_widget(form.destinationId.profession) -}}
            </div>
 
            <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
                {{- form_errors(form.destinationId.profession) -}}
            </div>
        </div>
 
        <br/>
 
        <div class="row">
            <p class="centered">Adresses</p>
 
            <div id="addressList" data-prototype="{{ form_widget(form.destinationId.addresses.vars.prototype)|e('html_attr') }}">
            </div>
        </div>
 
        <br/>
 
        <div class="row">
            <p class="centered">Medias</p>
 
            <div id="mediasList" data-prototype="{{ form_widget(form.destinationId.medias.vars.prototype)|e('html_attr') }}">
            </div>
        </div>
 
    </div>
 
    <br/>
{% endblock %}

Mon grand problème est d'ajouter les adresses et les moyens de contact pour chaque membre de famille en jQuery (car je suis nul en front en partie)... Je dois faire un Frankenstein à partir du code jQuery d'ajout de membre de famille + ajout d'une adresse + ajout d'un moyen de contact et je n'y arrive pas. Quelqu'un a une idée de comment résoudre ça ?


On a donc le code d'ajout d'adresse (standart)

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 
var collectionHolder;
 
// Set up an "add address" link
var addAddressLink = $('<a href="#" class="add_address_link">Add address</a>');
var newLinkP = $('<p class="centered"></p>').append(addAddressLink);
 
function addAddressForm(collectionHolder, newLinkP){
    // Get the data prototype
    var prototype = collectionHolder.data('prototype');
 
    // get the new index
    var index = collectionHolder.data('index');
 
    // Replace '__name__' in the prototype's HTML
    //instead be a number based on how many items we have
    var newForm = prototype.replace(/__name__/g, index);
 
    // Increase the index with one for the new item
    collectionHolder.data('index', index+1);
 
    //Display the form in the page nan li, before the "add address" link
    var newFormP = $('<div class="one-address"></div>').append(newForm);
    newLinkP.before(newFormP);
    addAddressDeleteLink(newFormP);
}
 
function addAddressDeleteLink(AddressFormP)
{
    var removeForm = $('<p class="centered"><a href="#" style="color:red">Delete Address</a></p>');
    AddressFormP.append(removeForm);
 
    removeForm.on('click', function(e){
        e.preventDefault();
 
        AddressFormP.remove();
    });
}
 
function handleAcData(collectionHolder,newLinkP)
{
    // Get the div that holds the collection of addresses
    collectionHolder = $('div#addressList');
 
    // add the "add address" anchor
    collectionHolder.append(newLinkP);
 
    // add a delete link to all of the existing media form elements
    collectionHolder.find('div#one-address').each(function(){
        addAddressDeleteLink($(this))
    });
 
    // Count the current form inputs
    // use that as the new index when inserting a new item
    collectionHolder.data('index', collectionHolder.find(':input').length);
 
    return collectionHolder;
}
 
jQuery(document).ready(function(){
    collectionHolder = handleAcData(collectionHolder, newLinkP);
    addAddressLink.on('click', function(e)
    {
        // Prevent the link from creating a "#" on the URL
        e.preventDefault();
        // add a new address form
        addAddressForm(collectionHolder, newLinkP);
    })
});
et de moyen de contact :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
var collectionHolder2;
 
// Set up an "add address" link
var addMediaLink = $('<a href="#" class="add_media_link">Add Contact mean</a>');
var newLinkP2 = $('<p class="centered"></p>').append(addMediaLink);
 
function addMediaForm(collectionHolder, newLinkP2){
    // Get the data prototype
    var prototype = collectionHolder.data('prototype');
 
    // get the new index
    var index = collectionHolder.data('index');
 
    // Replace '__name__' in the prototype's HTML
    //instead be a number based on how many items we have
    var newForm = prototype.replace(/__name__/g, index);
 
    // Increase the index with one for the new item
    collectionHolder.data('index', index+1);
 
    //Display the form in the page nan li, before the "add address" link
    var newFormP = $('<div class="one-media"></div>').append(newForm);
    newLinkP2.before(newFormP);
    addMediaDeleteLink(newFormP);
}
 
function addMediaDeleteLink(mediaFormP)
{
    var removeForm = $('<p class="centered"><a href="#" style="color:red">Delete Media</a></p>');
    mediaFormP.append(removeForm);
 
    removeForm.on('click', function(e){
        e.preventDefault();
 
        mediaFormP.remove();
    });
}
 
function handleMcData(collectionHolder2,newLinkP2)
{
    // Get the div that holds the collection of addresses
    collectionHolder2 = $('div#mediasList');
 
    // add the "add address" anchor
    collectionHolder2.append(newLinkP2);
 
    // add a delete link to all of the existing media form elements
    collectionHolder2.find('div#one-media').each(function(){
        addMediaDeleteLink($(this))
    });
 
    // Count the current form inputs
    // use that as the new index when inserting a new item
    collectionHolder2.data('index', collectionHolder2.find(':input').length);
 
    return collectionHolder2;
}
 
jQuery(document).ready(function(){
    collectionHolder2 = handleMcData(collectionHolder2, newLinkP2);
    addMediaLink.on('click', function(e)
    {
        // Prevent the link from creating a "#" on the URL
        e.preventDefault();
        // add a new address form
        addMediaForm(collectionHolder2, newLinkP2);
    })
});
Le problème est que si je met juste les 3 fichiers dans mon code, les collectionHolder de l'adresse et des moyens de contact ne sont pas chargés au click sur `ajouter un membre de famille`. J'ai essayé de placer le code d'ajout d'adresse et de moyen de contact dans le code
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
addFMemberLink.on('click',function(e)
    {
        // Prevent the link from creating a "#" on the URL
        e.preventDefault();
 
        // add a new address form
        addFmemberForm(familyCollectionHolder, newFamilyLinkP);
 
    });
Ca donne bien l'effet visuel mais l'index de l'adresse et du moyen de contact ne s'incrémente pas donc à la fin ca sauvegarde une adresse maximum et un moyen de contact maximum....

Merci pour votre aide !