I need a form theme for one field. I don't want to load it in the form _self.
So i did in config/packages/twig:
twig:
paths: ['%kernel.project_dir%/templates']
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
form_themes:
- 'form/calendarFormtheme.html.twig'
My form theme templates/form/calendarFormtheme.html.twig:
{%- block calendar_widget -%}
<div class="ui inline calendar" id="calendar_start">
<div class="ui disabled input left icon">
<i class="calendar icon"></i>
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" placeholder="hallo" {% endif %}/>
</div>
</div>
{%- endblock calendar_widget -%}
And in my formType:
$builder->add('start', DateTimeType::class, [
'block_name' => 'calendar_widget',
'label' => false,
'widget' => 'single_text',
'html5' => false,
'required' => true,
'attr' => [
'data-provide' => 'calendar',
'data-date-format' => 'yyyy-mm-dd HH:mm'
]
]);
But it's not loading the new theme.
Where is my mistake?
TXH
Related
I am trying to deal between Symfony 5 & Tempus Dominus Bootstrap4 Datetimepicker. My Datetime input form only work with an update function, when an event exist. I want to pass an attribute to my form but it seems to doesn't work.
I have this builder :
$builder->add('date', DateTimeType::class, [
'required' => true,
'widget' => 'single_text',
'attr' => [
'html5' => false,
'placeholder' => 'Date',
'class' => 'form-control datetimepicker-input',
'data-target' => '#datetimepicker1'
],
]);
My template :
<div class="row row-datetime">
<div class="input-group date col" id="datetimepicker1" data-target-input="nearest">
{{ form_widget(form.date, {'html5':false } ) }}
<div class="input-group-append" data-target="#datetimepicker1" data-toggle="datetimepicker">
<div class="input-group-text datetimepicker-button">
<i class="fa fa-clock"></i>
</div>
</div>
</div>
</div>
{% block javascripts %}
{{parent()}}
<script>
$('#datetimepicker1').datepicker({
format: 'dd.MM.yyyy',
});
</script>
{% endblock %}
But the result is unexpected, Chrome returns my input type as "datetime-local".
In another template for editing an existing event, I have this code, Without form_widget :
<div class="row row-datetime">
<div class="input-group date col" id="datetimepicker1" data-target-input="nearest">
<input type="text" class="form-control datetimepicker-input" data-target="#datetimepicker1"/>
<div class="input-group-append" data-target="#datetimepicker1" data-toggle="datetimepicker">
<div class="input-group-text datetimepicker-button">
<i class="fa fa-clock"></i>
</div>
</div>
</div>
</div>
And it works like a charm I don't understand... If I try this code in my first template, Twig create two datetime inputs. One with the datetimepicker and another classic datetime.
I really don't understand.
Can somebody help me with this please ?
Thanks.
Best,
Py
Change your builder to this:
$builder->add('date', DateTimeType::class, [
'required' => true,
'widget' => 'single_text',
'attr' => [
'placeholder' => 'Date',
'class' => 'datetimepicker-input',
'data-target' => '#datetimepicker1'
],
'html5' => false,
]);
Note that the html5 specification does not go in the attr array. Also note that you don't have to add the form-control class since symfony will do this on its own where needed.
To generate a simple menu, I can do:
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
and then:
{% embed '...' with { items: ['Home', 'Articles'] %}
But how do I have to write the TWIG code, if I want to create endless deep menus like:
<ul>
<li>Alpha</li>
<li>Bravo</li>
<ul>
<li>Charlie</li>
<li>Delta</li>
<li>Echo</li>
<ul>
<li>Foxtrott</li>
</ul>
<li>Golf</ul>
</ul>
<li>Hotel</li>
<li>India</li>
</ul>
Thx for help!
To perform recursion in twig you can make use of macro's
{% import _self as macro %}
{{ macro.multilevel(foo) }}
{% macro multilevel(array) %}
{% import _self as macro %}
<ul>
{% for item in array %}
<li>
{% if item is iterable %}
{{ macro.multilevel(item) }}
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endmacro %}
twigfiddle
EDIT With a simple array it's not possible to nest children in the same <li> as the parent. Herefor you would need to change your array arround,
Reformed array
$data = [
'links' => [
[
'title' => 'alpha',
'href' => 'http://www.alpha.com',
'children' => [],
],
[
'title' => 'beta',
'href' => 'http://www.beta.com',
'children' => [
[
'title' => 'charlie',
'href' => 'http://www.charlie.com',
'children' => [],
],
[
'title' => 'delta',
'href' => 'http://www.delta.com',
'children' => [],
],
[
'title' => 'echo',
'href' => 'http://www.echo.com',
'children' => [
[
'title' => 'foxtrot',
'href' => 'http://www.foxtrot.com',
'children' => [],
],
],
],
],
],
]
];
tiwg
{% macro menu(links) %}
{% import _self as macro %}
<ul>
{% for link in links %}
<li>
{{ link['title'] }}
{% if not link['children']|default([]) is empty %}
{{ macro.menu(link['children']) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endmacro %}
twigfiddle
Edit: see the solution I've found at the end of my question ;-)
I'm looking since hours for a solution but I do not really find what I'like. I'm sure it is easy to do.
I'm building a form with Symfony 3.1. My form does not send anything in a database. Everything seems okay. But when rendering my twig template all my checkbox are surrounded by a <div> html tag.
I just would like twig renders me a form without that <div> tag.
edit: this is what Twig render me: this is ok for me but I would like to remove div tags
<form name="form" method="post">
<div id="form"><div><label for="form_1">1</label><input type="checkbox" id="form_1" name="form[1]" class="ballsCheckBox" value="1" /></div>
</form>
Here is my twig template:
{% extends "::base.html.twig" %}
{% block title %}SimulotoBundle:Lotto:lotto{% endblock %}
{% block body %}
<h1>Welcome to the Lotto:result page</h1>
{{form(form)}}
{% endblock %}
I build the form directly in a controller. See it:
public function LottoSimulationFormAction()
{
$lt = new LottoSimulation();
$data = [];
$formBuilder = $this->createFormBuilder($data);
/** building Lotto grid with checkboxes * */
for ($i = 1; $i <= $lt->getMaxNb(); $i++)
{
$formBuilder->add($i, CheckboxType::class, [
'label' => $i,
'required' => false,
'attr' => [
'class' => 'ballsCheckBox'
]
]);
}
/** adding submit button **/
$formBuilder->add('Envoyer', SubmitType::class, [
'attr' => [
'class' => 'save'
]
]);
$form = $formBuilder->getForm();
return $this->render("SimulotoBundle:Lotto:lotto.html.twig", [
"form" => $form->createview()
]);
}
}
Here is the soluton to solve this problem.
I need to Customize the form rendering as it is explained in the Synfony cookBook on this page http://symfony.com/doc/current/form/form_customization.html
Go to vendor\Symfony\Bridge\Twig\Ressources\views\Form\form_div_layout.html and modify the block:
{%- block form_row -%}
<div>
{{- form_label(form) -}}
{{- form_errors(form) -}}
{{- form_widget(form) -}}
</div>
{%- endblock form_row -%}
You can remove it but a better way is to copy/past that block to your teplate and overide it. Like this:
{% extends "::base.html.twig" %}
{% form_theme form _self %} //don't forget this line of code
{%- block form_row -%}
{{- form_label(form) -}}
{{- form_errors(form) -}}
{{- form_widget(form) -}}
{%- endblock form_row -%}
I am using Silex micro faramework with Symfony forms. In twig templet I generate this field using :
...
{{ form_widget(form.transport_selection) }}
...
How can I overwrite this symfony twig form templet to generate wrap for each set (input field and label) in Silex.
This is my twig registration:
use Silex\Provider\FormServiceProvider;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Validator\Constraints as Assert;
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => [
__DIR__.'/App/View',
]
));
How to wrap radio button and label with div for each radio choice ?
output:
<div id="form_transport_selection">
<input type="radio" id="form_transport_selection_0" name="form[transport_selection]" required="required" value="country" checked="checked">
<label for="form_transport_selection_0" class="required">country</label>
<input type="radio" id="form_transport_selection_1" name="form[transport_selection]" required="required" value="abroad">
<label for="form_transport_selection_1" class="required">abroad</label>
</div>
Expected output:
<div id="form_transport_selection">
<div class="radio1">
<input type="radio" id="form_transport_selection_0" name="form[transport_selection]" required="required" value="country" checked="checked">
<label for="form_transport_selection_0" class="required">country</label>
</div>
<div class="radio2">
<input type="radio" id="form_transport_selection_1" name="form[transport_selection]" required="required" value="abroad">
<label for="form_transport_selection_1" class="required">abroad</label>
</div>
</div>
Thanks
You can make new template for this form and redefine radio buttons view
my.form.twig
{% extends "form_div_layout.html.twig" %}
{%- block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{% set i=1 %}
{%- for child in form %}
<div class="radio-{{i}}">
{{- form_widget(child) -}}
{{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
</div>
{% set i=i+1 %}
{% endfor -%}
</div>
{%- endblock choice_widget_expanded -%}
and use it in controller template, where form is shown
{% form_theme form 'my.form.twig' %}
....
{{ form_widget(form.transport_selection) }}
Expanding on MaxP's answer. Make sure to only modify this for radio buttons, you don't want this used in checkboxes! I've added a different class for checkboxes. Note the if/else to do this.
{% extends "form_div_layout.html.twig" %}
{% block choice_widget_expanded %}
<div {{ block('widget_container_attributes') }}>
{% set i=1 %}
{% for child in form %}
{% if form.vars.multiple == false %}
<div class="radio-{{i}}">
{% elseif form.vars.multiple == true %}
<div class="checkbox-{{i}}">
{% endif %}
{{ form_widget(child) }}
{{ form_label(child, null, {translation_domain: choice_translation_domain}) }}
</div>
{% set i=i+1 %}
{% endfor %}
</div>
{% endblock choice_widget_expanded %}
And use it in controller template, where form is shown
{% form_theme form 'my.form.twig' %}
....
{{ form_widget(form.transport_selection) }}
When using Symfony, I recommend overriding all Twig fields in app/Resources/views/Form/fields.html.twig
And then on config.yml you just need to make this available by adding it to twig's config
twig:
form_themes:
- 'Form/fields.html.twig'
Problem
I'm using yii2 with the twig templating engine. It seems to be working however I can't seem to use any of the methods of the Html helpers (yii/helpers/Html).
My view is extending a base layout using twig extends. {% extends "#layouts/_base.twig" %}
I am including 'yii/helpers/Html' in the _base.twig file. {{ use('yii/helpers/Html') }}
I'm using {{ html.encode(this.title) }} to render the page title in the header and
{{ html.submitButton('Send Message', {
'class': 'button button--cta button--expand',
}) | raw }}
to try and render a button in my view but neither seems to work, I don't get any errors, just nothing rendering.
Question
Have I set this up correctly? What should I have to do to render a button in yii2 twig? Very new to using twig.
Code
index.twig
{% extends "#layouts/_base.twig" %}
{% block layout %}
...
{% set form = active_form_begin({
'id' : 'contact-us-form'
}) %}
...
<div class="row">
<div class="medium-8 medium-offset-2 columns">
{{ form.field(contact_us, 'full_name').textArea([{
'rows' : 6,
'placeholder' : 'Let us know if you have any questions...'
}]).label('Message', {
'class' : 'label--inline'
}) | raw }}
</div>
</div>
<div class="row">
<div class="medium-3 medium-offset-2 columns">
{{ html.submitButton('Send Message', {
'class': 'button button--cta button--expand',
}) | raw }}
</div>
</div>
{{ active_form_end() }}
</section>
{% endblock %}
_base.twig
{{ use('yii/helpers/Html') }}
{{ use('yii/widgets/ActiveForm') }}
{{ use('yii/web/JqueryAsset') }}
{{ this.beginPage() }}
<!DOCTYPE html>
<html lang="{{app.language}}">
<head>
{{ this.head() }}
<meta charset="{{app.charset}}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link href='https://fonts.googleapis.com/css?family=Lato:300,400,700,900' rel='stylesheet' type='text/css'>
{{ html.csrfMetaTags() | raw }}
{{ register_asset_bundle('www/assets/AppAsset') }}
<title>{{ html.encode(this.title) }}</title>
</head>
<body>
{{ this.beginBody() }}
{% block header %}
{% include "#layouts/components/header.twig" %}
{% endblock %}
{% block layout %}
{% endblock %}
{% block footer %}
{% include "#layouts/components/footer.twig" %}
{% endblock %}
{{ this.endBody() }}
</body>
</html>
{{ this.endPage() }}
To use \yii/helpers\Html helper in twig templates you need to configure twig extension accordingly. This is covered in documentation, Additional Configuration page.
You need to add 'globals' option inside 'twig' section of configuration (see 'THIS LINE' mark):
For yiisoft/yii2-twig version 2.1.0:
[
'components' => [
'view' => [
'class' => 'yii\web\View',
'renderers' => [
'twig' => [
'class' => 'yii\twig\ViewRenderer',
'cachePath' => '#runtime/Twig/cache',
// Array of twig options:
'options' => [
'auto_reload' => true,
],
/* *THIS LINE* */ 'globals' => ['html' => ['class'=>'\yii\helpers\Html']],
'uses' => ['yii\bootstrap'],
],
// ...
],
],
],
]
Then just use it in template as 'html' variable, example:
{{ html.csrfMetaTags() | raw }}
For yiisoft/yii2-twig version 2.0.6 and earlier there was old syntax:
'globals' => ['html' => '\yii\helpers\Html'], // *THIS LINE*
According actual documentation, the correct form must be:
[
'components' => [
'view' => [
'class' => 'yii\web\View',
'renderers' => [
'twig' => [
'class' => 'yii\twig\ViewRenderer',
'cachePath' => '#runtime/Twig/cache',
// Array of twig options:
'options' => [
'auto_reload' => true,
],
'globals' => ['html' => ['class'=>'\yii\helpers\Html']], // *THIS LINE*
'uses' => ['yii\bootstrap'],
],
// ...
],
],
],
]
I don't know why, the former "html"=>'\yii\helpers\html' not works in one of my recents projects.