why does my symfony2 Form not submit?
If i press the submit-button, nothing happens.
I want not the default-form {{ form(form) }}.
The default form works.
The error seems to be in TWIG?
{% extends '::base.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('css/essensplan/show.css') }}" rel="stylesheet" />
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
{% endblock %}
{% block body -%}
{{ form_start(form) }}
<h1>Speiseplan für KW {{ kw }}</h1>
<form action = "" method = "post">
<input type="submit" name="back" value="<" class="btn-lg btn-success"/>
<input type="submit" name="next" value=">" class="btn-lg btn-success" />
<input type="hidden" name="kw" value="{{ kw }}">
</form>
<div class="container-fluid">
<div class="tag col-xs-3">
<div class="wochentag">
Montag
</div>
<div class="hauptgericht">
<div class="h"><strong>Hauptgericht</strong></div>
<div class=""> {{ form_widget(form.montagHauptgericht) }}
</div>
</div>
<div class="nachtisch">
<div class="n"><strong>Nachtisch</strong></div>
<div class=""> {{ form_widget(form.montagNachtisch) }} </div>
</div>
</div>
</div>
{{ form_widget(form.Eintragen) }}
{{ form_end(form) }}
{% endblock %}
<?php
namespace Chris\TestBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Chris\TestBundle\Entity\KW;
use Chris\TestBundle\Form\KWType;
use Symfony\Component\HttpFoundation\Session\Session;
/**
* Admin controller.
*
*/
class AdminController extends Controller
{
/**
* Lists all KW entities.
*
*/
public function adminAction(Request $request)
{
$jahr = "2014";
$kw = "43";
// $_GET parameters
// Änderung
if ($request->get('next')){
$kw = (intval($request->get('kw'))+1) . "";
//var_dump($kw);
}
if ($request->get('back')){
$kw = (intval($request->get('kw'))-1) . "";
//var_dump($kw);
}
$form = $this->createFormBuilder()
->add('montagHauptgericht', 'text')
->add('montagNachtisch', 'text')
->add('Eintragen', 'submit')
->getForm();
$form->handleRequest($request);
// data is an array with "name", "email", and "message" keys
$data = $form->getData();
return $this->render('ChrisTestBundle:KW:admin.html.twig', array(
'form' => $form->createView(), 'kw' => $kw
));
}
}
Thanks for your help.
It seems that you have nested forms in your markup (first one coming from twig's {{ form }} second is in markup. According to this or this you are not allowed to nest form tags. This might be the reason your form is not submitting properly
Related
The following error occurred in Symfony4.
There are many posts with the same error, but I couldn't find the one in this case.
When I deleted the //Error part in the Twig file, the error disappeared, so I know it's the cause, but I don't know how to fix it.
What are your good ideas?
However, deleteAction is not used in //Error part and is incomprehensible.
The CSRF token is invalid. Please try to resubmit the form.
Article.php
protected function deleteAction(Request $request, $ids)
{
$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('authenticate', $token);
if (!$this->get("security.csrf.token_manager")->isTokenValid($csrf_token)) {
//Error code
throw new HttpException("400", "The CSRF token is invalid. Please try to resubmit the form.");
}
}
index.html.twig
{{ form_start(form) }}
<div class="formGroup trendTags"
data-prototype="{{ macros.trendTagForm(form.trendTags.vars.prototype)|e }}"
data-index="{{ ec_tag_contents|length }}">
<label>Tag</label>
<button type="button" class="add btn">Add</button>
<ul class="trend-tag-list2" {% if not ec_tag_contents|default %} style="display:none"{% endif %} id="trendTagsWrap">
{% for tag in ec_tag_contents|default %}
<li>
<div class="tagForm">
<div class="input-trendtag-display-name"> {{ tag.name }}</div>
<div class="input-trendtag-display-term">({{ tag.str_tag_display }} {{ tag.str_term }})</div>
<br>
{% for category in tag.categories|split(',') %}
<div class="tag-form__category-sticker" name="{{ category }}">{{ category }}</div>
{% endfor %}
<button class="removeTrendTag"><i class="icon-remove"></i></button>
</div>
<div id="brandevent_trendTags_{{ loop.index0 }}">
<input type="hidden" id="brandevent_trendTags_{{ loop.index0 }}_trendTagId" name="brandevent[trendTags][{{ loop.index0 }}][trendTagId]" required="required" value="{{ tag.tag_id }}">
</div>
</li>
{% endfor %}
{% do form.trendTags.setRendered(true) %}
</ul>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
{% set url = path("app_hq_article_index", {"articleType": "article", "num": 5, "modal": true}) %}
<div id="relatedArticleDialog" title="Article Selection" data-url="{{ url }}">
</div>
//Error part
{% set q = app.request.query.get("q")|default({}) %}
{% set trendTagUrl = path("app_hq_article_trendtag", {"q[sex]": q.sex|default(0), "q[brand_id]": q.brand_id|default(), "q[del_flg]": 0}) %}
<div id="trendTagDialog" title="Tag Selection" data-url="{{ trendTagUrl }}">
</div>
trendTag.html.twig
<div class="search">
{% include '#AppBundle/Shop/Article/trendTagForm.html.twig' %}
</div>
trendTagForm.html.twig
<form id="frm-trend-tag-search" name="frm-trend-tag-search" method="get" action="{{path('app_hq_article_trendtag')}}">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
...
</form>
Add the {{form_widget(form._token)}} hidden field to the main form
or
Disable the CSRF token in form config:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'csrf_protection' => false,
]);
}
I am trying to create a simple form within Symfony. Not quite sure why this is not grabbing the form variable.
Receiving error:
Variable "form" does not exist src/Thinkfasttoys/MapWatchBundle/Resources/views/Default/createMapPolicy.html.twig at line 30
Controller - DefaultController.php
class DefaultController extends Controller
{
public function policyFormAction()
{
$form = $this->createFormBuilder()
->add('name', 'text')
->add('age', 'integer')
->add('save', 'submit')
->getForm()
;
return $this->render('ThinkfasttoysMapWatchBundle:Default:createMapPolicy.html.twig', array(
'form' => $form->createView(),
));
}
View - createMapPolicy.html.twig
{% block body %}
<div class="row-fluid">
<div class="span12">
<div class="widget-box">
<h4 align="center", padding="10px 0 10px 0">Create a New MAP Policy</h4>
{{ form(form) }}
<div class="container-1">
</div><!-- /.container -->
</div><!-- /.widgetbox -->
</div>
</div>
{% endblock %}
In twig you have to display the form like this:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
I have simple edit form where the user will have to fill up required fields. The problem is the validation of required fields doesn't show, and also the fields or data don't change.
UPDATE I var_dump the $form->isSubmitted() and it shows bool(false)
Here's my controller:
public function editAction(Request $request, $id) {
$company = $this->getDoctrine()
->getRepository('SwipeBundle:Company')
->find($id);
if(!$company) {
throw $this->createNotFoundException(
'No Company found for id '.$id
);
}
$form = $this->createForm(CompanyType::class, $company, array(
'action'=>$this->generateUrl('swipe_backend_company_edit', array('id'=>$company->getId())),
'method'=>'PUT'
));
if ($request->getMethod() == "POST") {
if ($form->isSubmitted()) {
// $em->persist($company);
// $em->flush();
echo "Update";
}
}
return $this->render('Backend/Company/edit.html.twig', array(
'form'=>$form->createView(),
'company'=>$company
));
}
And here's my twig template:
{% extends '::Backend/base.html.twig' %}
{% block body %}
<!-- Section -->
<section class="sections">
<!-- Side Bar -->
{% include '::Backend/side_menu_bar.html.twig' %}
<!-- Wrapper -->
<div id="administrator" class="wrapper">
<div class="mt40 pt30"> <!-- Container -->
<h1 class="mb10 bold">Edit Company</h1>
<p class="mb30">Fill up all the required fields for Company.</p>
{% if not form.vars.valid %}
<p class="alert note-error">
There are errors in your form. Please check the fields marked in red.
</p>
{% endif %}
<div class="alert note-error">
<p>Fields with asterisk (*) are required</p>
</div>
{% set url = path('swipe_backend_company_edit', { 'id': company.id }) %}
<form novalidate method="post" action="{{ url }}" class="p20 card mb30">
<div class="sections pb30 pt10">
<fieldset class="col span6">
{% set attr = {} %}
{% if form_errors(form.name) is not empty %}
{% set attr = attr|merge({ 'class': 'alert error'}) %}
{% endif %}
<label for="" class="input-required">
<strong>Company Name<span class="highlight-red">*</span>
</strong>
</label>
{{ form_widget(form.name, { 'attr': attr } ) }}
{% if not form.name.vars.valid %}
<p class="mt10" style="color: #DC2B1B;">
{{ form.name.vars.errors[0].message }}
</p>
{% endif %}
</fieldset>
<fieldset class="col span6">
<strong>
{{ form_label(form.website) }}
</strong>
{{ form_widget(form.website) }}
</fieldset>
</div>
<div class="sections pb30 pt10">
{% set attr = {} %}
{% if form_errors(form.email_address) is not empty %}
{% set attr = attr|merge({ 'class': 'alert error'}) %}
{% endif %}
<label for="" class="input-required">
<strong>Company Email Address<span class="highlight-red">*</span>
</strong>
</label>
{{ form_widget(form.email_address, { 'attr': attr } ) }}
{% if not form.email_address.vars.valid %}
<p class="mt10" style="color: #DC2B1B;">
{{ form.email_address.vars.errors[0].message }}
</p>
{% endif %}
</div>
<div class="sections pb30 pt10">
<fieldset class="col span6">
<strong>
{{ form_label(form.telephone_no) }}
</strong>
{{ form_widget(form.telephone_no) }}
</fieldset>
<fieldset class="col span6">
<strong>
{{ form_label(form.mobile_no) }}
</strong>
{{ form_widget(form.mobile_no) }}
</fieldset>
</div>
<div class="sections pb30 pt10">
{% set attr = {} %}
{% if form_errors(form.address) is not empty %}
{% set attr = attr|merge({ 'class': 'alert error'}) %}
{% endif %}
<label for="" class="input-required">
<strong>Company Address<span class="highlight-red">*</span>
</strong>
</label>
{{ form_widget(form.address, { 'attr': attr } ) }}
{% if not form.address.vars.valid %}
<p class="mt10" style="color: #DC2B1B;">
{{ form.address.vars.errors[0].message }}
</p>
{% endif %}
</div>
<div class="text-right mt20 mb10">
<button class="btn btn-positive mt10 mr5">Update Company</button>
<button class="btn btn-positive mt10 mr5">Cancel</button>
</div>
{{ form_rest(form) }}
</form>
</div> <!-- Container End -->
</div> <!-- Wrapper End -->
</section> <!-- Section End -->
{% endblock %}
Only one action for edit / Update the record
public function editAction($id) {
$em = $this->getDoctrine()->getManager();
$company = $em
->getRepository('SwipeBundle:Company')
->find($id);
if(!$company) {
throw $this->createNotFoundException(
'No Company found for id '.$id
);
}
$form = $this->createForm(CompanyType::class, $company, array(
'action'=>$this->generateUrl('swipe_backend_company_update', array('id'=>$company->getId())),
'method'=>'PUT'
));
if ($request->getMethod() == "POST") {
if ($form->isValid()) {
$em->persist($company);
$em->flush();
}
}
return $this->render('Backend/Company/edit.html.twig', array(
'form'=>$form->createView(),
'company'=>$company
));
}
and also Change the form action in twig same a edit action
Make sure this is useful to you.
I have a private message bundle/entity that allows my users to send messages between them.
Its fields are as follows:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #Assert\NotBlank(message="private_message.title.blank")
* #ORM\Column(name="title", type="string", length=50)
*/
protected $title;
/**
* #Assert\NotBlank(message="private_message.receiver.blank")
* #AcmeAssert\IsHimself(message="private_message.receiver.himself", groups={"new"})
* #ORM\ManyToOne(targetEntity="MedAppBundle\Entity\User")
* #ORM\JoinColumn(referencedColumnName="id")
*/
protected $receiver;
/**
* #ORM\ManyToOne(targetEntity="MedAppBundle\Entity\User")
* #ORM\JoinColumn(referencedColumnName="id")
*/
protected $sender;
/**
* #var string
* #Assert\NotBlank(message="private_message.content.blank")
* #ORM\Column(name="content", type="string")
*/
protected $content;
/**
* #var \DateTime
*
* #ORM\Column(name="sentAt", type="datetime")
*/
protected $sentAt;
/**
* #var boolean
*
* #ORM\Column(name="isSpam", type="boolean")
*/
protected $isSpam = false;
/**
* #var \DateTime
*
* #ORM\Column(name="seenAt", type="datetime",nullable=true)
*/
protected $seenAt = null;
/**
* #ORM\ManyToOne(targetEntity="PrivateMessageBundle\Entity\Message",inversedBy="replies")
* #ORM\JoinColumn(referencedColumnName="id",nullable=true)
*/
protected $replyof;
/**
* #ORM\OneToMany(targetEntity="PrivateMessageBundle\Entity\Message", mappedBy="replyof")
**/
private $replies;
public function __construct() {
$this->replies = new ArrayCollection();
}
Notice the replyof field, it references to another message, and the replies one references to an array of messages. If replyof is null, then the message is not a reply of any message.
I have a twig template with a macro that displays a user's message and all the replies of that message. What I'd like to do is have a reply textfield under each of these, exactly like Gmail has, that allows me to add a reply to each message.
But when I add it to the template, only one is rendered because it has one single Id. How can I add a reply form after each reply? What their FormType should look like?
Here is also my twig template:
{% macro displayReply(reply,replyform) %}
{% import _self as macros %}
{# <li> id: {{ reply.id }} </li>
<li> sent by: {{ reply.sender }} </li>
<li> title: {{ reply.title }} </li>
<li> content: {{ reply.content }} </li>
<li> date: {{ reply.sentAt|date('d-m-Y H:i:s') }} </li>
reply
<hr> #}
<div class="panel panel-default">
<div class="panel-body">
<div class="message-info">
<input type="hidden" name="messageid" id="messageId" value="{{ reply.id }}">
<div class="message-title clearfix">
<h4 class="pull-left">{{ reply.title }}</h4>
</div>
<hr class="lite-line">
<div class="message-sender clearfix">
<div class="pull-left sender">
{{ reply.sender }}
</div>
<div class="pull-right">
to <b>{{ (reply.receiver==app.user)?'me':reply.receiver }}</b> on <span
class="message-timestamp">{{ reply.sentAt|date('F d, Y H:i:s') }}</span>
<a class="btn btn-start-order" role="button"
href="{{ path('private_message_new',{'msg':reply.id}) }}">Reply</a>
</div>
</div>
<hr class="lite-line">
<div class="message-box clearfix">
<span>{{ reply.content | replace({"<script>" : "", "</script>" : ""}) | raw }}</span>
</div>
{{ form_start(replyform) }}
<input type="submit">
{{ form_end(replyform) }}
</div>
</div>
</div>
{% for reply in reply.replies %}
{% if loop.first %}<div>{% endif %}
{{ macros.displayReply(reply) }}
{% if loop.last %}</div>{% endif %}
{% endfor %}
{% endmacro %}
{% import _self as macros %}
{# use the macro #}
<div class="message-back">
<a class="btn btn-start-order-dark btn-block" role="button"
href="{{ path('private_message',{'page':'inbox'}) }}">
<span class="fa fa-undo"></span> Go back
</a>
</div>
<div class="messages">
<div class="panel panel-default">
<div class="panel-body">
<div class="message-info">
<input type="hidden" name="messageid" id="messageId" value="{{ message.id }}">
<div class="message-title clearfix">
<h4 class="pull-left">{{ message.title }}</h4>
</div>
<hr class="lite-line">
<div class="message-sender clearfix">
<div class="pull-left sender">
{{ message.sender }}
</div>
<div class="pull-right">
to <b>{{ (message.receiver==app.user)?'me':message.receiver }}</b> on <span
class="message-timestamp">{{ message.sentAt|date('F d, Y H:i:s') }}</span> <a
class="btn btn-start-order" role="button"
href="{{ path('private_message_new',{'msg':message.id}) }}">Reply</a>
</div>
</div>
<hr class="lite-line">
<div class="message-box clearfix">
<span>{{ message.content | replace({"<script>" : "", "</script>" : ""}) | raw }}</span>
</div>
{{ form_start(replyform) }}
<input type="submit">
{{ form_end(replyform) }}
</div>
</div>
</div>
</div>
{% for reply in message.replies %}
{% if loop.first %}<div class="replies">{% endif %}
{{ macros.displayReply(reply ,replyform) }}
{% if loop.last %}</div>{% endif %}
{% endfor %}
Notice that I first display the message, then apply the macro to it that displays all its replies as a tree. It will display the replies's replies, too, in a recursive manner, all the way until the leaf nodes. I add a 'replyform' after each, but I'm not sure how the FormType should be.
My reply form type is like this, but I'm pretty sure it is wrong.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('content', 'textarea')
;
}
As for the other fields of the reply, I take care of them in the controller. I think I should be doing this after receiving the message from the form though. Something like this, and get the title, content and replyof from the formdata.
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$isforme = $messages->findOneBy(array('receiver' => $this->getUser(), 'id' => $msg));
$message = new Message();
$message->setSender($this->getUser());
$message->setSentAt(new \Datetime('now'));
$message->setReplyof($isforme);
$message->setReceiver($isforme->getSender());
$form = $this->createForm(new MessageReplyType($em), $message);
EDIT
Ok, so I made something that works, by adding a hidden field and hardcoding multiple forms instead of using FormTypes, but I still think that this can be done in a better, more reusable way.
<form name="privatemessagebundle_message" method="post" action="" id="{{ reply.id }}">
<div><label for="privatemessagebundle_message_title" class="required">Title</label><input
type="text" id="privatemessagebundle_message_title"
name="privatemessagebundle_message[title]" required="required" maxlength="50"></div>
<div><label for="privatemessagebundle_message_content" class="required">Content</label><textarea
id="privatemessagebundle_message_content"
name="privatemessagebundle_message[content]" required="required"></textarea></div>
<input type="hidden" id="privatemessagebundle_message_replyof"
name="privatemessagebundle_message[replyof]" value="{{ reply.id }}">
<input type="submit">
<input type="hidden" id="privatemessagebundle_message__token"
name="privatemessagebundle_message[_token]"
value="{{ csrf_token('privatemessagebundle_message') }}">
</form>
Anyone got any better ideas?
I did it! I used the answer from this question.
Since I'm using foreach loops and they might be a bit low on performance, anyone with a better idea is welcomed. There is still the bounty to receive.
I'm creating a form for each of my forms through createNamedBuilder. They will have different names, thus different id's and Symfony will render them all. Then, I can render them where I want and handle their request just fine through their unique id taken from the database.
$genforms = $this->genReplyForms($isforme); // run the function for my message
$forms_views = $genforms['views']; // pass to the view
$forms= $genforms['forms']; // handle request...
This is the function that generated the form. It recursively generates them for each reply of my message.
public function genReplyForms(Message $message)
{
$id = $message->getId();
$msgreply[$id] = new Message();
$forms[$id] = $this->container
->get('form.factory')
->createNamedBuilder('form_'.$id, new MessageReplyType(), $msgreply[$id])
->getForm();
$forms_views[$id] = $forms[$id]->createView();
$result = array(array(), array());
$result['forms'][$id] = $forms[$id];
$result['views'][$id] = $forms_views[$id];
if (sizeof($message->getReplies())) {
foreach ($message->getReplies() as $reply) {
$child = $this->genReplyForms($reply);
$result['forms'] = $result['forms'] + $child['forms'];
$result['views'] = $result['views'] + $child['views'];
}
}
return $result;
}
MessageReplyType needs just user input. Everything else is handled in the controller
$builder
->add('title')
->add('content', 'textarea')
;
Also, my simplified twig. I've simplified the macro call, too. Was doing an unnecessary foreach loop for the first message instead of simply passing it to the macro.
{% macro displayReply(reply, forms) %}
{% import _self as macros %}
{# <li> id: {{ reply.id }} </li>
<li> sent by: {{ reply.sender }} </li>
<li> title: {{ reply.title }} </li>
<li> content: {{ reply.content }} </li>
<li> date: {{ reply.sentAt|date('d-m-Y H:i:s') }} </li>
reply
<hr> #}
<div class="panel panel-default">
<div class="panel-body">
<div class="message-info">
<input type="hidden" name="messageid" id="messageId" value="{{ reply.id }}">
<div class="message-title clearfix">
<h4 class="pull-left">{{ reply.title }}</h4>
</div>
<hr class="lite-line">
<div class="message-sender clearfix">
<div class="pull-left sender">
{{ reply.sender }}
</div>
<div class="pull-right">
to <b>{{ (reply.receiver==app.user)?'me':reply.receiver }}</b> on <span
class="message-timestamp">{{ reply.sentAt|date('F d, Y H:i:s') }}</span>
{# <a class="btn btn-start-order" role="button"
href="{{ path('private_message_new',{'msg':reply.id}) }}">Reply</a> #}
</div>
</div>
<hr class="lite-line">
<div class="message-box clearfix">
<span>{{ reply.content | replace({"<script>" : "", "</script>" : ""}) | raw }}</span>
</div>
{{ form_start(forms[reply.id]) }}
<input type="submit">
{{ form_end(forms[reply.id]) }}
{# NU STERGE! #}
{#
<form name="privatemessagebundle_message" method="post" action="" id="{{ reply.id }}">
<div><label for="privatemessagebundle_message_title" class="required">Title</label><input
type="text" id="privatemessagebundle_message_title"
name="privatemessagebundle_message[title]" required="required" maxlength="50"></div>
<div><label for="privatemessagebundle_message_content" class="required">Content</label><textarea
id="privatemessagebundle_message_content"
name="privatemessagebundle_message[content]" required="required"></textarea></div>
<input type="hidden" id="privatemessagebundle_message_replyof"
name="privatemessagebundle_message[replyof]" value="{{ reply.id }}">
<input type="submit">
<input type="hidden" id="privatemessagebundle_message__token"
name="privatemessagebundle_message[_token]"
value="{{ csrf_token('privatemessagebundle_message') }}"></form>#}
{# NU STERGE! #}
</div>
</div>
</div>
{% for reply in reply.replies %}
{% if loop.first %}<div>{% endif %}
{{ macros.displayReply(reply,forms) }}
{% if loop.last %}</div>{% endif %}
{% endfor %}
{% endmacro %}
{% import _self as macros %}
{# use the macro #}
<div class="message-back">
<a class="btn btn-start-order-dark btn-block" role="button"
href="{{ path('private_message',{'page':'inbox'}) }}">
<span class="fa fa-undo"></span> Go back
</a>
</div>
<div class="replies">
{{ macros.displayReply(message, forms) }}
</div>
Again, I'm still looking for better or more efficient alternatives, so please do post them.
I would like to override a specific element of my Symfony form, while allowing my standard template to generate the rest of the fields. So far it has been a case of either/or.
First my template generates the form element
<form action="" method="post" {{ form_enctype(form) }} autocomplete="off">
{% form_theme form 'SuperSecretProjectBundle:Default:collection.html.twig' %}
{{ form_widget(form) }}
<input type="submit" class="right submit button primary small" value="Save" />
</form>
Inside collection.html.twig I have the following blocks: form_row is the generic widget renderer, while image_sets_row is my specific row I want to override.
{% block form_row %}
<div class="row">
<div class="large-12 columns{% if not form.vars.valid %}error{% endif %}">
{{ form_label(form) }}
{{ form_widget(form) }}
<small>{{ form_errors(form) }}</small>
</div>
</div>
{% endblock form_row %}
{% block image_sets_row %}
<div id="image_sets">
<div class="row">
<div class="columns large-12">
Add image set
</div>
</div>
</div>
{% endblock %}
This results in using form_row for all fields, without my modified block. How can I have Symfony output the elements that are not being specifically overridden and include my new blocks as well?
What you need is a custom field type for the field you are trying to use your custom widget for.
As shown in the link, first you need to create a custom Field Type class like so
// src/AppBundle/Form/Type/ImageSetsType.php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; #should change to whatever parent type you need
class ImageSetsType extends AbstractType{
public function configureOptions(OptionsResolver $resolver){
$resolver->setDefaults( array() ); #set any option defaults you need here
}
public function getParent(){
return ChoiceType::class; #again change this to whatever parent type you need
}
}
Next we get your template for that block working properly
{# app/Resources/views/form/fields.html.twig #}
{% block imagesets_widget %}
<div id="image_sets">
<div class="row">
<div class="columns large-12">
{{ form_label(form) }}
{{ form_widget(child) }}
Add image set
<small>{{ form_errors(form) }}</small>
</div>
</div>
</div>
{% endblock %}
Then you use your newly created type in your form as you would any other.
As I assume you want a little more in