I'm working on symfony(4.2) project with CMS option. So I decided to use Sonata bundles to achieve the CMS like WP. Currentl I've installed and using SonataAdminBundle, SonataMediaBundle, SonataBlockBundle...etc. Also I've created custom service with basic form fields for page blocks and it works fine for me. Now I want to create a form with repeater field like clone system
I've created a new form type named CloneType and customized the form template. Also added the CloneType field in block service file and now the form looks like this below image
https://i.stack.imgur.com/WmYFg.png
my inputs is looking like this when inspect in browser
<input type="text" id="s9fdc9db89c_settings_cxi_different_title" name="s9fdc9db89c[settings][cxi_different][title_1]" class=" form-control" value="test">
<input type="text" id="s9fdc9db89c_settings_cxi_different_title" name="s9fdc9db89c[settings][cxi_different][title_2]" class=" form-control" value="test">
src/Form/Type/CloneType.php
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CloneType extends AbstractType
{
public function getParent()
{
return FormType::class;
}
}
templates/sonataadmin/forms/clone.twig.html
{% block clone_widget %}
{% spaceless %}
<div class="clone-wrapper">
<div id="clonedInput1" class="clonedInput">
{{- form_widget(form) -}}
{{- form_errors(form) -}}
<div class="actions">
<a class="btn btn-info clone">Clone</a>
<a class="btn btn-warning remove">Remove</a>
</div>
</div>
</div>
{% endspaceless %}
{% block javascripts %}
<script type="text/javascript">
var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;
function clone(){
$(this).parents(".clonedInput").clone()
.appendTo("clone-wrapper")
.attr("id", "clonedInput" + cloneIndex)
.find("*")
.each(function() {
var id = this.id || "";
var match = id.match(regex) || [];
if (match.length == 3) {
this.id = match[1] + (cloneIndex);
}
})
.on('click', 'a.clone', clone)
.on('click', 'a.remove', remove);
cloneIndex++;
}
function remove(){
$(this).parents(".clonedInput").remove();
}
$("a.clone").on("click", clone);
$("a.remove").on("click", remove);
</script>
{% endblock %}
{% endblock %}
src/Application/Sonata/BlockBundle/Block/CxiDifferentBlockService.php
<?php
namespace App\Application\Sonata\BlockBundle\Block;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Sonata\Form\Type\ImmutableArrayType;
use Sonata\Form\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Meta\Metadata;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\BlockBundle\Block\Service\AbstractBlockService;
use App\Application\Sonata\PageBundle\Entity\Block;
use App\Form\Type\CloneType;
use Sonata\AdminBundle\Admin\AdminInterface;
class CxiDifferentBlockService extends AbstractBlockService
{
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
$formMapper
->add('settings', ImmutableArrayType::class, [
'keys' => [
['title', TextType::class, [
'label' => 'Title (H2)',
'required' => false,
]],
[$this->getCloneBuilder($formMapper), null, []],
],
])
;
}
protected function getCloneBuilder(FormMapper $formMapper)
{
return $formMapper->create('cxi_different', CloneType::class, ['required' => false,'by_reference' => false,'allow_extra_fields'=>true])
->add('title', TextType::class,['required' => false, 'allow_extra_fields'=>true, 'by_reference' => false])
;
}
}
I want to update the cloned field values in DB. But its not working. I checked the data while submit the form. The sonata form is not added the cloned fields in the post array. The post array is looks like below actual result
Actual Result :
Array(
[title] => test
[cxi_different] => Array
(
[title_1] => test
)
)
Expected Result :
Array(
[title] => test
[cxi_different] => Array
(
[title_1] => test
[title_2] => test
)
)
Thanks in advance!