Lets say i have a one to many relation:
Now, I want to display all pictures of a company within a template. And i also want to make theese pictures directly editable. I thought of adding a form to each Entity of the DoctrineArrayCollection and pass them to the template. In Template if somebody clicks on a picture the corresponding should be fade in, the should be able to edit the pictures description and pass it through ajax to a controller.
In my entity I added a field without annotations:
private $form;
public function setForm(MyPictureForm $form)
{
$this->form = $form;
}
public function getForm()
{
return $this->form;
}
Now in my controller I add a form instance to every picture of the company:
//office images with forms
$officeImages = array();
foreach($company->getOfficeImages() as $image)
{
$form = $this->get('companybundle.imagedescription.form.factory')->createForm();
$form->setData($image);
$image->setForm($form->createView());
array_push($officeImages, $image);
}
return $this->render('CompanyBundle:Company:Show/show.html.twig', array(
'company' => $company,
'officeImages' => $officeImages
));
}
And in my template i render it like this way:
{% for image in officeImages %}
<a href="#" title="{% if image.description %}{{ company.description }}{% else %}CLICK HERE FOR EDIT{% endif %}">
{% if image.image %}
<img src="{{ vich_uploader_asset(image, 'image') | imagine_filter('company_office_image_thumb') }}"
alt="{% if image.description %}{{ company.description }}{% endif %}"/>
{% else %}
{% image '@UserBundle/Resources/public/img/nopic_logo.jpg' output='/images/nopic_logo.jpg' %}
<img src="{{ asset_url }}" alt="Joblogo"/>
{% endimage %}
{% endif %}
</a>
{{ form(image.form) }}
{% else %}
<p>Es sind noch keine Images vorhanden</p>
{% endfor %}
At the end there is a lot if javascript stuff which handels the fade in / fade out of the form and their submitting.
Is this the correct way to handle my case? I think not cause passing a form for every picture seems like overhead?
The reason why I am working with forms instead of simply passing data out of a manual added input field is csrf protection and the smart usage of the form component.
As you said keeping form object in entity isn't a good idea. It should represents model data.
I've got two solutions for this:
I. Pass array of forms with image id as a key
$officeImages = array();
$imageForms = array();
foreach($company->getOfficeImages() as $image)
{
$form = $this->get('companybundle.imagedescription.form.factory')->createForm();
$form->setData($image);
$imageForms[$image->getId()] = $form->createView();
}
return $this->render('CompanyBundle:Company:Show/show.html.twig', array(
'company' => $company,
'officeImages' => $officeImages,
'imageForms' => imageForms
));
and in show.html.twig
{% for image in officeImages %}
{# your image display code #}
{{ form(imageForms[image.id]) }}
{% endfor %}
II. render partial for single image
in controller
public function showAndEditImageAction(Image $image)
{
$form = $this->get('companybundle.imagedescription.form.factory')->createForm();
$form->setData($image);
return $this->render(
'CompanyBundle:Company:Show/showAndEditImage.html.twig', array(
'image' => $image,
'imageForm' => $form->createView()
));
}
in twigs
{# CompanyBundle:Company:Show/showAndEditImage.html.twig #}
{# your image display code #}
{{ form(imageform) }}
{# CompanyBundle:Company:Show/show.html.twig #}
{% for image in officeImages %}
{{ render(controller('CompanyBundle:Company:showAndEditImage',
{ 'image': image })) }}
{% endfor %}