简体   繁体   中英

Symfony2, Typeahead, form collection

I have this section of Javascript for a form collection in Symfony2.

$(document).ready(function() {
  // Create Input Text
  $(document).on('click', '.btn-add[data-target]', function(event) {

    event && event.preventDefault();

    var collectionHolder = $('#' + $(this).attr('data-target'));

    if (!collectionHolder.attr('data-counter')) {
      collectionHolder.attr('data-counter', collectionHolder.children().length);
    }

    var prototype = collectionHolder.attr('data-prototype');
    var form = prototype.replace(/__name__/g, collectionHolder.attr('data-counter'));

    collectionHolder.attr('data-counter', Number(collectionHolder.attr('data-counter')) + 1);
    collectionHolder.append(form);

    typeInitialize();

    return false;

  });

  // Remove Input Text
  $(document).on('click', '.btn-remove[data-related]', function(event) {

    event && event.preventDefault();

    var name = $(this).attr('data-related');

    ($('*[data-content="'+ name +'"]')).remove();

  });

  // Initialize Typeahead
  function typeInitialize() {

    // Create typeahead instance
    var url = Routing.generate('ajax_search', {name: 'WILDCARD'});
    // Trigger typeahead + bloodhound
    var products = new Bloodhound({
      datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      identify: function(obj) { return obj.u_name; },
      prefetch: 'json/result.json',
      remote: {
        url: url,
        wildcard: 'WILDCARD',
      }
    });

    products.initialize();

    $('.typeahead').typeahead({
      minLength: 3,
      highlight: true,
      limit: 10,
    },
    {
      name: 'product',
      display: 'u_name',
      source: products.ttAdapter()
    });
  }
});

The Twig Template:

{% extends '::base.html.twig' %}
{% block body %}
{% macro widget_prototype(widget, remove_text) %}
{% if widget.vars.prototype is defined %}
    {% set form = widget.vars.prototype %}
    {% set name = widget.vars.prototype.vars.full_name %}
{% else %}
    {% set form = widget %}
    {% set name = widget.vars.full_name %}
{% endif %}
<div data-content="{{ name }}">
    <div class="btn-remove">
      <a class="btn-remove" data-related="{{ name }}">{{ remove_text }}</a>
    </div>
    {{ form_widget(form) }}
</div>
{% endmacro %}

<div class="row">
  <div class="col-md-12">
    <a class="btn-add" class="clicked" data-target="post_tags">Adauga Produs</a>
    {{form_start(form, {'attr': {'class': 'form-horizontal'}})}}
    {{form_row(form.name)}}
    <div id="post_tags" data-prototype="{{ _self.widget_prototype(form.product, 'Delete Product')|escape }}">
        {% for widget in form.product.children %}
            {{ _self.widget_prototype(widget, 'Delete Product') }}
        {% endfor %}
    </div>
    {{form_end(form)}}
  </div>
</div>
{% endblock %}

The code doesn't contain any errors been testing it all day long, but when I try to add a new field it adds it with no problem and the second field it adds the second field but on the first field it adds an empty span from typeahead then when I add the third field it adds another empty span to the first element. On forth field it adds to the first second and third input an empty span for typeahead . From what I believe, the problem is from typeInitialize function and how I call it, but I couldn't figure it out myself what I did wrong on this part and then the second problem is when I click on remove it removes all the inputs that I added.

I changed the entire code fixed the problems. Here is the updated version for anyone who needs it.

// setup an "add a tag" link
var $addTagLink = $('<a href="#" class="btn btn-primary add_tag_link">Adauga Produs</a>');
var $newLinkLi = $('#post_tags').append($addTagLink);

jQuery(document).ready(function() {
    // Get the ul that holds the collection of tags
   var $collectionHolder = $('#post_tags');

    // add the "add a tag" anchor and li to the tags ul
    $collectionHolder.append($newLinkLi);

    // count the current form inputs we have (e.g. 2), use that as the new
    // index when inserting a new item (e.g. 2)
    $collectionHolder.data('index', $collectionHolder.find(':input').length);

    $addTagLink.on('click', function(e) {
        // prevent the link from creating a "#" on the URL
        e.preventDefault();

        // add a new tag form (see code block below)
        addTagForm($collectionHolder, $newLinkLi);

        typeInitialize();
    });


});

function addTagForm($collectionHolder, $newLinkLi) {
    // Get the data-prototype explained earlier
    var prototype = $collectionHolder.data('prototype');

    // get the new index
    var index = $collectionHolder.data('index');

    // Replace '$$name$$' in the prototype's HTML to
    // 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 next item
    $collectionHolder.data('index', index + 1);

    // Display the form in the page in an li, before the "Add a tag" link li
    var $newFormLi = $('<div class="post_tags"></div>').append(newForm);

    // also add a remove button, just for this example
    $newFormLi.append('<a href="#" class="btn btn-warning remove-tag">Sterge Produsul</a>');

    $newLinkLi.before($newFormLi);

    // handle the removal, just for this example
    $('.remove-tag').click(function(e) {
        e.preventDefault();

        $(this).parent().remove();

        return false;
    });
}
// Initialize Typeahead
function typeInitialize() {

  // Create typeahead instance
  var url = Routing.generate('ajax_search', {name: 'WILDCARD'});
  // Trigger typeahead + bloodhound
  var products = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    identify: function(obj) { return obj.u_name; },
    prefetch: 'json/result.json',
    remote: {
      url: url,
      wildcard: 'WILDCARD',
    }
  });

  products.initialize();



  $('.post_tags').find('input[type=text]:last').typeahead({
    minLength: 3,
    highlight: true,
    limit: 10,
  },
  {
    name: 'product',
    display: 'u_name',
    source: products.ttAdapter()
  }).on('typeahead:selected', function (e, datum) {
    console.log(datum);
  });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM