Тип поля коллекции не создает элементы формы

Я пытаюсь создать форму, которая будет добавлять новое текстовое поле каждый раз, когда будет нажата ссылка «Добавить новое поле». Я прочитал следующий пример. http://symfony.com/doc/current/reference/forms/types/collection.html

В основном я следовал примеру из книги. Но когда страница отображается и я нажимаю на ссылку, ничего не происходит. Какие-нибудь мысли? Спасибо.

Это мой контроллер.

 public function createAction() {
    $formBuilder = $this->createFormBuilder();

    $formBuilder->add('emails', 'collection', array(
        // each item in the array will be an "email" field
        'type'   => 'email',
        'prototype' => true,
        'allow_add' => true,
        // these options are passed to each "email" type
        'options'  => array(
            'required'  => false,
            'attr'      => array('class' => 'email-box')
        ),
    ));
    $form = $formBuilder->getForm();

    return $this->render('AcmeRecordBundle:Form:create.html.twig', array(
        'form' => $form->createView(),
    ));
}

Это точка зрения.

 <form action="..." method="POST" {{ form_enctype(form) }}>
{# store the prototype on the data-prototype attribute #}
<ul id="email-fields-list" data-prototype="{{ form_widget(form.emails.get('prototype')) | e }}">
{% for emailField in form.emails %}
    <li>
        {{ form_errors(emailField) }}
        {{ form_widget(emailField) }}
    </li>
{% endfor %}
</ul>

<a href="#" id="add-another-email">Add another email</a>
</form>

<script type="text/javascript">
// keep track of how many email fields have been rendered
var emailCount = '{{ form.emails | length }}';

jQuery(document).ready(function() {
    jQuery('#add-another-email').click(function() {
        var emailList = jQuery('#email-fields-list');

        // grab the prototype template
        var newWidget = emailList.attr('data-prototype');
        // replace the "$$name$$" used in the id and name of the prototype
        // with a number that's unique to our emails
        // end name attribute looks like name="contact[emails][2]"
        newWidget = newWidget.replace(/\$\$name\$\$/g, emailCount);
        emailCount++;

        // create a new list element and add it to our list
        var newLi = jQuery('<li></li>').html(newWidget);
        newLi.appendTo(jQuery('#email-fields-list'));

        return false;
    });
})
</script>

person Dhanushka    schedule 19.04.2012    source источник
comment
Трудно ответить, видя вывод консоли из Chrome/Firebug. По моему опыту, когда я делал свой, я предполагаю, что data-prototype не заполнялся или что-то подобное. Часть моей точки зрения состоит в том, чтобы сделать максимально общий вариант и никогда не использовать конкретный javascript (например, ваш пример #add-another-email... Скажите, помог ли вам мой ответ.   -  person renoirb    schedule 20.06.2012


Ответы (2)


Эту проблему можно решить, перейдя по следующей ссылке.

https://github.com/beberlei/AcmePizzaBundle

Здесь вы найдете тот же функционал, который реализуется.

person Ashwin Preetham Lobo    schedule 20.04.2012
comment
Спасибо. Я попробую. - person Dhanushka; 20.04.2012

Я тоже прошел через это.

Ответ и примеры на этот вопрос и другой вопрос, который я нашел, не ответил моя проблема тоже.

Вот как я это сделал, в какой-то общей манере.

В общем, я имею в виду, что любой collection, который я добавляю в форму, просто должен следовать циклу шаблон формы (например, в макросе), и все!

Используя какое соглашение

Класс типа формы

class OrderForm extends AbstractType
{
// ...

public function buildForm(FormBuilder $builder, array $options)
{
// ...
  $builder
  ->add('sharingusers', 'collection', array(
          'type' => new UserForm(),
          'allow_add' => true,
          'allow_delete' => true,
          'by_reference' => false,
          'required'=> false
  ));
// ...
}
}

JavaScript

/* In the functions section out of document ready */

/**
 * Add a new row in a form Collection
 *
 * Difference from source is that I use Bootstrap convention
 * to get the part we are interrested in, the input tag itself and not
 * create a new .collection-field block inside the original.
 * 
 * Source: http://symfony.com/doc/current/cookbook/form/form_collections.html
 */
function addTagForm(collectionHolder, newBtn) {
    var prototype = collectionHolder.attr('data-prototype');
    var p = prototype.replace(/\$\$name\$\$/g, collectionHolder.children().length);
    var newFormFromPrototype = $(p);
    var buildup = newFormFromPrototype.find(".controls input");
    var collectionField = $('<div class="collection-field"></div>').append(buildup);
    newBtn.before(collectionField);
}


/* ********** */
$(document).ready(function(){


   /* other initializations */


    /**
     * Form collection behavior
     *
     * Inspired, but refactored to be re-usable from Source defined below
     *
     * Source: http://symfony.com/doc/current/cookbook/form/form_collections.html
     */
    var formCollectionObj = $('form .behavior-collection');
    if(formCollectionObj.length >= 1){
        console.log('run.js: document ready "form .behavior-collection" applied on '+formCollectionObj.length+' elements');
        var addTagLink = $('<a href="#" class="btn"><i class="icon-plus-sign"></i> Add</a>');
        var newBtn = $('<div class="collection-add"></div>').append(addTagLink);
        formCollectionObj.append(newBtn);
        addTagLink.on('click', function(e) {
            e.preventDefault();
            addTagForm(formCollectionObj, newBtn);
        });
    }


   /* other initializations */

});

Шаблон формы

Хитрость здесь в том, что я бы использовал исходный {{ form_widget(form }}, но мне нужно было добавить некоторые особенности в форму просмотра, и я не мог сделать ее короче.

И я попытался только редактировать целевое поле и обнаружили, что это немного сложно

Вот как я это сделал:

            {# All form elements prior to the targeted field #}
            <div class="control-collection control-group">
                <label class="control-label">{{ form_label(form.sharingusers) }}</label>
                <div class="controls behavior-collection" data-prototype="{{ form_widget(form.sharingusers.get('prototype'))|escape }}">
                {% for user in form.sharingusers %}
                    {{ form_row(user) }}
                {% endfor %}
                </div>
            </div>
            {{ form_rest(form) }}
person renoirb    schedule 20.06.2012