如何使用jQuery动态编辑集合字段(ZF2)

I have a Collection created with ZF2. The HTML code looks for eg as follows:

<fieldset id="benutzer">
<legend>Team</legend>
<div class="controls-row">
 <span data-template="<input type="hidden" name="projekt[benutzer][__placeholder__][benutzerid]" class="benutzerid" value=""><input name="projekt[benutzer][__placeholder__][benutzername]" class="benutzername" title="Kollege" placeholder="Name" type="text" value=""><input type="hidden" name="projekt[benutzer][__placeholder__][bearbeiten]" value="0"><input type="checkbox" name="projekt[benutzer][__placeholder__][bearbeiten]" title="Bearbeiten" class="bearbeiten" value="1"><input name="projekt[benutzer][__placeholder__][bemerkung]" title="Bemerkung" placeholder="Bemerkung" type="text" value="">"></span>
<input type="hidden" value="4" class="benutzerid" name="todo[benutzer][0][benutzerid]">
<input type="text" value="Julian" placeholder="Name" title="Kollege" class="benutzername" name="todo[benutzer][0][benutzername]">
<input type="hidden" value="0" name="todo[benutzer][0][bearbeiten]">
<input class="bearbeiten" type="checkbox" checked="checked" value="1" title="Bearbeiten" name="todo[benutzer][0][bearbeiten]">
<input type="text" value="" placeholder="Bemerkung" title="Bemerkung" name="todo[benutzer][0][bemerkung]">
<div>
<div class="row">
<input type="hidden" value="5428" class="benutzerid" name="todo[benutzer][0][benutzerid]">
<input type="text" value="Hans" placeholder="Name" title="Kollege" class="benutzername" name="todo[benutzer][0][benutzername]">
<input type="hidden" value="0" name="todo[benutzer][0][bearbeiten]">
<input class="bearbeiten" type="checkbox" checked="checked" value="1" title="Bearbeiten" name="todo[benutzer][0][bearbeiten]">
<input type="text" value="" placeholder="Bemerkung" title="Bemerkung" name="todo[benutzer][0][bemerkung]">
<div>
</fieldset>

The user should now be able to check/uncheck the checkboxes, edit the input fields but also delete and/or add rows. The collections of ZF2 need the indexes of its rows to start at 0 and count up each row by 1. This means, if I delete a row and the row was not adventitiously at the end of the collection, I have to correct the indexes. I am trying to do this with jQuery.

And here is my Porblem: If I changed anything before I re-sort the rows (and I do this in the end everytime before I submit the form), the changes are not preserved. If I check a checkbox, if I enter something to the "Bemerkung"-field, everything will be discarded.

Here is my code:

Add a new row:

function add_category( $collectionType ) {
    // Create and append new row
    var $template = $('#'+$collectionType+' span').data('template');
    var $currentCount = $('#'+$collectionType+' .'+$collectionType+'id').length;
    $template = $template.replace(/__placeholder__/g, String($currentCount));
    $newrow = "<div class=\"controls-row new-row\">"+$template+"<div class=\"span1\"><a href=\"#\" class=\"_delete-row\"><i class=\"icon-remove\"></i></a></div></div>";
    $('#'+$collectionType).append($newrow);         
    return false;
}

Re-sort the collection:

 $.fn.resortCollection = function (){   // execute with Collection-Fieldset!
            $c = 0; 
            $fieldset = $(this);
            // re-sort the rows, indexes
            $.each( $fieldset.find('.controls-row'), function(){            
                $html = $(this).html();
                $newhtml = $html.replace(/\[\d+\]/g, '['+$c+']');
                $(this).html($newhtml);
                $c++;
            });
        }; 

Delete a row in the collection:

 $.fn.deleteRow = function (){
            var $row = this.closest('div.controls-row');
            var $fieldset = $row.closest('fieldset');
            $($row).remove();
            $fieldset.resortCollection();
        };

How can I access the current state of the DOM including my changes while re-sorting the rows?

Actually Zend\Form\Element\Collection preserves the keys of a collection. The only problem that i found is that if you initially define collection with the option count > 0 e.g.:

    $this->add(array(
        'type' => 'Zend\Form\Element\Collection',
        'name' => 'data',
        'options' => array(
            'count' => 2,
            'allow_add' => true,
        )
    ));

it will always add as much missing elements at the begining of the collection as you defined with count option. From the example above it will add elements with indexes 0 and 1 if they are missing in the collection.

I fixed that by extending Zend\Form\Element\Collection and rewriting one method:

namespace MyNamespace;

use Zend\Form\Element\Collection as ZendCollection;
use Zend\Form\Exception;
use Traversable;

class MyCollection extends ZendCollection
{
    public function populateValues($data)
    {
        if (!is_array($data) && !$data instanceof Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects an array or Traversable set of data; received "%s"',
                __METHOD__,
                (is_object($data) ? get_class($data) : gettype($data))
            ));
        }

        if (sizeof($data)){
            foreach ($this->byName as $name => $element) {
                if (!isset($data[$name])) {
                    $this->remove($name);
                }
            }
        }

        parent::populateValues($data);
    }
}

Hope it will help you to simplify your code.