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.