Form theme in Twig / Symfony - symfony

With Symfony and Twig, I have this form and this form theme :
TrainingVersionType (this is collection) :
class TrainingVersionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, [
'attr' => [
'autofocus' => true,
],
'label' => 'label.training_name',
'ico' => 'pencil',
'translation_domain' => 'administration',
])
->add('document', FineUploaderType::class, [
'label' => 'label.attachments',
'translation_domain' => 'administration',
'limit' => 1,
'acceptFiles' => [
'image/jpeg',
'image/png',
],
'allowedExtensions' => [
'jpg',
'jpeg',
'png',
],
])
;
}
Form theme in my Twig file :
{% block _training_versions_entry_name_widget %}
<strong style="background: red; padding: 20px">
Ok 1 :)
</strong>
{% endblock %}
{% block _training_versions_entry_document_widget %}
<strong style="background: blue; padding: 20px">
Ok 2 :)
</strong>
{% endblock %}
Why I have "OK 1" and I don't have "OK 2" ?
In my config.yml, I have this global form theme, But this is Widget for "FineUploaderType" :
{% block fineuploader_widget %}
<div class="qq-uploader-selector card mb-3 bg-light">
<div class="card-body">
<div class="qq-upload-button-selector">
<span class="btn btn-info">
{{ 'action.select'|trans({}, 'fineuploader') }}
</span>
</div>
</div>
</div>
....
{% endblock %}
I want to add div in "document" entry in the form, for add help after FineUploader widget.
Can you help me ? :) Thanks
Edit :
administration/training/new.html.twig :
{% form_theme form 'administration/training/_form_theme.html.twig' %}
{% block content %}
{{ include('default/page/_new.html.twig', {
form: form,
btn_ico: 'plus',
btn_value: 'action.training_new'|trans({}, 'administration'),
back_label: 'action.training_back'|trans({}, 'administration'),
back_path: path('administration_training')
},
with_context = false
) }}
{% endblock %}
administration/training/_form_theme.html.twig :
{% block _training_versions_entry_name_widget %}
<strong style="background: red; padding: 20px">
Ok 1 :)
</strong>
{% endblock %}
{% block _training_versions_entry_document_widget %}
<strong style="background: blue; padding: 20px">
Ok 2 :)
</strong>
{% endblock %}

Related

How to use template form when edit object

I have a form with an embedded form (collectionType). I made a template. It works when I add a new object. But how to use this template when I edit an object ? Below my code an 2 pictures to illustrate my problem
{% extends 'base.html.twig' %}
{% form_theme form _self %}
{% block _paris_rencontres_row %}
<div class="sports" id="renc-xx" style="background-color: rgba(182, 184, 185, 0.200);">
<div
class="row">
{# <ul class="sports" data-prototype="{{ form_widget(form.vars.prototype)|e('html_attr') }}"></ul> #}
<div class="col-md-3">
{{ form_row(form.vars.prototype.playedAt) }}
</div>
<div class="col-md-3">
{{ form_row(form.vars.prototype.sport) }}
</div>
</div>
<div class="row">
<div class="col-md-3">
{{ form_row(form.vars.prototype.player_1) }}
</div>
<div class="col-md-3">
{{ form_row(form.vars.prototype.player_2) }}
</div>
<div class="col-md-2">
{{ form_row(form.vars.prototype.cote) }}
</div>
<div class="col-md-2">
{{ form_row(form.vars.prototype.resultat) }}
</div>
</div>
<hr>
</div>
{% endblock %}
{% block body %}
{# {{ include('paris/_form.html.twig', {form:form, button: 'Ajouter'}) }} #}
<button type='button' id='btn-add' class='add_sport_link btn btn-primary'>Ajouter paris</button>
{{ form_start(form) }}
<div class="paris">
<div class="row">
<div class="col-md-4">
{{ form_row(form.mise) }}
</div>
<div class="col-md-4">
{{ form_row(form.type) }}
</div>
<div class="col-md-4">
{{ form_row(form.win) }}
</div>
</div>
<div class="col-md-4 matchs">
{% if form.rencontres|length > 0 %}
{% for index in 0..form.rencontres|length - 1 %}
{{ dump(index) }}
{{ form_row(form.rencontres[index]) }}
{% endfor %}
{% else %}
{{ form_row(form.rencontres) }}
{% endif %}
</div>
</div>
{{ form_end(form) }}
{% endblock %}
add (form.rencontres|length == 0):
enter image description here
edit (form.rencontres|length > 0):
enter image description here
Regards
PS: Sorry for my english
EDIT: My controller
#NicoHaase I dont think the problem is in the code.
I want just display my form template when I edit an object as when I add an object
`code
/**
* #Route("/paris/add", name="paris_add")
*/
public function add(Request $request)
{
$em = $this->getDoctrine()->getManager();
$paris = new paris();
$form = $this->createForm(ParisType::class, $paris);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($paris);
$em->flush();
return $this->redirectToRoute('paris');
}
return $this->render("paris/add.html.twig", [
'form' => $form->createView()
]);
}
/**
* #Route("/paris/{id}", name="paris_edit", requirements={"id":"\d+"})
* #param Paris $paris
* #param Request $request
*/
public function edit(Request $request, Paris $paris)
{
$form = $this->createForm(ParisType::class, $paris);
$form->handleRequest($request);
return $this->render("paris/add.html.twig", [
"paris" => $paris,
"form" => $form->createView(),
]);
}
`

Customize symfony data-prototype for edit form

I know it's a common question but I cannot figure out how to achieve that.
I have a Course entity and a CourseDocument entity.
Course(id, documents, ...)
CourseDocument(id, file, course)
In my Course form:
class CourseType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, [
'label' => 'course.title',
])
->add('documents', CollectionType::class, array(
'entry_type' => MediaType::class,
'label' => 'course.documents_list',
'entry_options' => array(
'label' => false,
'data_class' => CourseDocument::class,
),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
))
;
}
In the form I want to be able to add as many documents as I want. I set up everything, javascript included. My only issue is the data-prototype that is not what I want.
{% import "macros/prototype.html.twig" as prototype %}
{{ form_start(form) }}
<div class="row">
<div class="col-md-6">
<fieldset class="form-group">
{{ form_label(form.documents) }}
<div id="course_documents" class="collection_holder" data-prototype="{{ prototype.tagCollectionItem(form.documents.vars.prototype)|e }}">
{% for widget in form.documents %}
{{ prototype.tagCollectionItem(widget) }}
{% endfor %}
</div>
<button type="button" id="add-document-btn" data-target-collection="#{{ form.documents.vars.id }}" class="btn btn-sm btn-info"><i class="la la-plus"></i> {{ 'course.buttons.add_document' | trans({}, 'labels') }}</button>
</fieldset>
</div>
</div>
{{ form_end(form) }}
I'm generating my prototype with a macro:
{% macro tagCollectionItem(item) %}
<fieldset class="form-group">
<div id="{{ item.vars.id }}">
<div class="custom-file">
{{ form_widget(item.uploadedFile) }}
{{ form_label(item.uploadedFile, item.uploadedFile.vars.label, {'label_attr': {'class': 'custom-file-label'}}) }}
</div>
</div>
</fieldset>
{% endmacro %}
It's working pretty well except for editing. I don't want the input if I already selected a file. But I want the name of the file.
I finally used a macro.
{% macro tagCollectionItem(item) %}
<fieldset class="form-group">
<div id="{{ item.vars.id }}">
{% if item.uploadedFile.vars.file_url or item.uploadedFile.vars.image_url %}
{{ form_errors(item.uploadedFile) }}
{{ form_widget(item.uploadedFile, {'attr': {'hidden': true}}) }}
{% else %}
<div class="custom-file">
{{ form_widget(item.uploadedFile) }}
{{ form_label(item.uploadedFile, item.uploadedFile.vars.label, {'label_attr': {'class': 'custom-file-label'}}) }}
</div>
{% endif %}
</div>
</fieldset>
{% endmacro %}
The twig file for the form
<fieldset class="form-group">
{{ form_label(form.documents) }}
<div id="course_documents" class="collection_holder" data-prototype="{{ prototype.tagCollectionItem(form.documents.vars.prototype)|e }}">
{% for widget in form.documents.children %}
{{ prototype.tagCollectionItem(widget) }}
{% endfor %}
</div>
<button type="button" id="add-document-btn" data-target-collection="#{{ form.documents.vars.id }}" class="btn btn-sm btn-info"><i class="la la-plus"></i> {{ 'course.buttons.add_document' | trans({}, 'labels') }}</button>
</fieldset>

how to override ProfileFormType to edit users? symfony2

I'm working with symfony2.I'm using FOSUserBundle, so i want to override FormType of edit user to add name to builder. so how i should do it?
what i've did :
ProfileFormType :
<?php
namespace UserBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use FOS\UserBundle\Form\Type\ProfileFormType as BaseType;
class ProfileFormType extends BaseType {
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
// add your custom field
$builder->add('name')
->add('roles', 'collection', array(
'type' => 'choice',
'options' => array(
'choices' => array(
'ROLE_ADMIN' => 'Admin'))))
->add('image', new ImageType())
;
}
public function getName() {
return 'user_edit_profile';
}
}
services.yml
user.edit.form.type:
class: UserBundle\Form\Type\ProfileFormType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: user_edit_profile }
edit.html.twig
{% extends "UserBundle::layout.html.twig" %}
{% block body %}
<center> <h1> Modification de profile </h1> </center>
<aside class="col-sm-3">
<div class="panel panel-default">
<div class="panel-heading">Modification</div>
<div class="panel-body">
Veuillez remplir les champs
</div>
</div>
</aside>
<!--timeline-->
<section class="timeline col-sm-9">
<!--post Timeline-->
<div class="thumbnail thumbnail-post">
<!--caption-->
<div class="caption">
<form action="{{ path('fos_user_registration_register') }}" {{ form_enctype(form) }} method="POST" class="form-horizontal">
<div class="form-group">
{{ form_errors(form.name) }}
<div class="col-sm-9">
Name {{ form_widget(form.name, { 'attr': {'class': 'form-control', 'placeholder': 'form.name'|trans } }) }}
</div>
</div>
<div class="form-group">
{{ form_errors(form.email) }}
<div class="col-sm-9">
Email {{ form_widget(form.email, { 'attr': {'class': 'form-control', 'placeholder': 'form.email'|trans } }) }}
</div>
</div>
<div class="form-group">
{{ form_errors(form.username) }}
<div class="col-sm-9">
Pseudo {{ form_widget(form.username, { 'attr': {'class': 'form-control', 'placeholder': 'form.username'|trans } }) }}
</div>
</div>
<div class="form-group">
{{ form_errors(form.current_password) }}
<div class="col-sm-9">
Mot de passe actuelle {{ form_widget(form.current_password, { 'attr': {'class': 'form-control', 'placeholder': 'form.current_password'|trans } }) }}
</div>
</div>
</br>
{{ form_rest(form) }}
<div class="form-group">
<div class="col-md-4 col-sm-4 col-xs-12 col-md-offset-3">
<input class="btn btn-default submit" type="submit" value="{{ 'registration.submit'|trans }}">
</div>
</div>
</form>
</div> <!--#caption-->
<!--#post timeline-->
</div>
<!--#timeline-->
</section>
{% endblock %}
{% block js %}
<script>
$(document).ready(function () {
$('#roles').hide();
});
</script>
{% endblock %}
i'm getting this error :
Neither the property "name" nor one of the methods "name()",
"getname()"/"isname()" or "__call()" exist and have public access in
class "Symfony\Component\Form\FormView" in
FOSUserBundle:Profile:edit.html.twig at line 28.
How can i resolve that.
profile:
form:
type: fos_user_profile
It needs that at config.yml of fos
Update your service file:
user.edit.form.type:
class: UserBundle\Form\Type\ProfileFormType
arguments: [%fos_user.model.user.class%]
decorates: fos_user.profile.form.type
tags:
- { name: form.type, alias: user_edit_profile }
fos_user.profile.form.type is mean our name of service which will be replace our service that name user.edit.form.type
Add use Symfony\Component\Form\FormBuilderInterface;
You got error:
Neither the property "name" nor one of the methods "name()", "getname()"/"isname()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView" in FOSUserBundle:Profile:edit.html.twig at line 28.
due to fos_user_user table has not name field. If you want to add field whitch not locate in table you'll should add field those fields in entity generate getters and setters and finaly create new migration and migrate up.

Formbuilder Symfony2 - Searching by subcategory

I have tried this code in my twig : some stupid tests :/
<form class="form-horizontal" id="form-search" action="{{path('search_robe')}}" method="POST" enctype="multipart/form-data">
{% for robeoption in robeoptions %}
{% if robeoption.values|length>0 %}
<div class="col-md-3 col-sm-3 col-xs-3 ">
<div class="Robeoption-title">
{{robeoption.translate.title}}
</div>
<div class="Robeoption-value">
{% for robeoptionval in robeoption.values %}
<label>
<input type="checkbox" class="radio" value="1" name="{{robeoption.translate.title}}" />{{robeoptionval.translate.title}}</label>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</form>
I have this code in my Form Type
class SearchrobeType extends AbstractType {
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('robeoptions', 'entity', array(
'required' => false,
'class' => 'BrainAdminBundle:RobeOption',
/** #Ignore */
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('s')
->Join('s.values', 'values')
->groupBy('s.id');
},
'label' => true,
'multiple' => true,
'expanded' => true,
))
->add('robeoptionvalue', 'entity', array(
'required' => false,
'class' => 'BrainAdminBundle:RobeOptionValue',
/** #Ignore */
'label' => false,
'multiple' => true,
'expanded' => true,
))
;
}
So, the point is that i Have Two entities : robeoption and robeoptionvalues which have a oneTomany relation , I'm new to Symfony and I want to use the formBuilder in my twig so it will be something like that instead :
<form class="form-horizontal" id="form-search" action="{{path('search_robe')}}" method="POST" enctype="multipart/form-data">
{{form_widget(form.robeoptions)}} //
{{form_widget(form.robeoptionvalue)}}
</form>
I want to show each Robeoption in a label and just under each one its Robeoptionsvalue with an input checkbox button, Any help plz?
There is only one way to do that : it's to do it dynamically from my twig `
<form class="form-horizontal col-md-12 col-sm-12 col-xs-12" id="form-search" action="{{path('searchrobe')}}" method="POST" enctype="multipart/form-data">
<div class="sh" style="display:none;">
{{form_row(form._token)}}
<div class="col-md-12 col-sm-6 search-slide">
{% for robeoption in robeoptions %}
{% if robeoption.values|length>0 %}
<div class="col-md-4 col-sm-4 col-xs-4 ">
<div class="Robeoption-title">
<label> {{robeoption.translate.title}} </label>
</div>
<div class="Robeoption-value">
{% for robeoptionval in robeoption.values %}
<input type="checkbox" name="robeoptionValues[{{robeoptionval.id}}]" />{{robeoptionval.translate.title}}<br>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="col-md-12 col-sm-12 search-slide">
<div class="col-md-12 col-sm-12 contour">
<button class="btn btn-default btn-slider">{{'search'|trans({})}}</button>
</div>
</div>
</div>
</form>
And then get the array of options from controller
if ($_request->getMethod() == 'POST') {
$optionsvalues=$_request->request->get('robeoptionValues');
$robe = $_em->getRepository('BrainAdminBundle:Robe')->searchforRobes($optionsvalues);
}
searchforRobes($optionsvalues); Is a function in the Robe Repository

How to resize columns and center content in sonata admin bundle

How to resize columns and center content in sonata admin bundle?
you can ovveride the layout.css from sonataAdmin
As #ibasaw suggested, override the standard base_list_field.html.twig template by creating a new template as follows:
{# templates/list_entry_with_fixed_width.html.twig #}
{% extends '#SonataAdmin/CRUD/base_list_field.html.twig' %}
{% block field %}
<div style="width: 100px; text-align: center;">
{{ value }}
</div>
{% endblock %}
Or, if you want to keep the ability to use the 'collapse' option, copy the original code and extend it:
{# templates/list_entry_with_fixed_width.html.twig #}
{% extends '#SonataAdmin/CRUD/base_list_field.html.twig' %}
{% block field %}
{% apply spaceless %}
{% if field_description.option('collapse') is not null %}
{% set collapse = field_description.option('collapse') %}
<div class="sonata-readmore"
data-readmore-height="{{ collapse.height|default(40) }}"
data-readmore-more="{{ collapse.more|default('read_more')|trans({}, 'SonataAdminBundle') }}"
data-readmore-less="{{ collapse.less|default('read_less')|trans({}, 'SonataAdminBundle') }}"
style="width: 100px; text-align: center;"
>
{{ value }}
</div>
{% else %}
<div style="width: 100px; text-align: center;">
{{ value }}
</div>
{% endif %}
{% endapply %}
{% endblock %}
Then use that template to render a field in the list view:
protected function configureListFields(ListMapper $list): void
{
$list
->add(
'name',
null,
[
'template' => 'list_entry_with_fixed_width.html.twig',
]
);
}
(sonata-project/admin-bundle: 4.0.1)

Resources