I know about options like with_seconds or with_minutes, but im looking for something to stop rendering my hours input in DateTimeType field. For now it looks like this:
My question how is possible to avoid this input in second row ?
Maybe with form themes, but i want to consider with another option.
My RegistrationFormType:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('sex', ChoiceType::class, array(
'choices' => array(
'Mężczyzna' => 'Mężczyzna',
'Kobieta' => 'Kobieta'
),
'expanded'=> true,
'multiple' => false,
'required' => true
));
$builder->add('birthday_date', DateTimeType::class, array(
'placeholder' => array(
'year' => 'Year', 'month' => 'Month', 'day' => 'Day'
),
'years' => range(1960, 2017),
'with_minutes' => false,
'hours' => array()
));
$builder->add('about_me', TextareaType::class);
}
public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
}
public function getBlockPrefix()
{
return 'app_user_registration';
}
}
I'm using FOSUserBundle, so this is my form template for now:
{% trans_default_domain 'FOSUserBundle' %}
{{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }}
{{ form_widget(form) }}
<div>
<input type="submit" value="{{ 'registration.submit'|trans }}" />
</div>
{{ form_end(form) }}
Thanks you in advance !
Why using DateTimeType if you don't need time ?
Try using DateType or BirthdayType (doc
)
Related
I'm using the kevinPast adminLte bundle on symfony 5. Every datetype got their own format(dd-MM-YYYY) and you can't update it as a normal way by writing 'format' => 'yyyy-MM-dd' inside the form for example. The problem occurs also for other datetype, like birthday.
I also try to use my own datepicker function to override the existing one, but it's a bundle, so it first not work, then it broke also the existing js.
You can see the different try i did:
->add('startTime', DateTimeType::class, [
'required' => true,
'error_bubbling' => false,
'date_widget' => 'single_text',
// #todo Can we make this format configurable?
'date_format' => 'yyyy-MM-dd', // must match data-date-format as defined in field.html.twig
'minutes' => range(0, 55, 5)
])
it will show the data like that
it use the block date_widget on twig, the single_text area
{% block date_widget %}
{% if widget == 'single_text' %}
<div class="input-group">
<div class="input-group-addon">
<i class="far fa-calendar-alt"></i>
</div>
{% if type is not defined or type != 'date' %}
{% if attr.class is defined %}
{% set class = attr.class ~ ' timepicker' %}
{% else %}
{% set class = ' timepicker' %}
{% endif %}
{% set attr = attr|merge({'class' : class, 'data-datepickerenable':'on'}) %}
{% endif %}
{{ block('form_widget_simple') }}
</div>
{% else %}
{% set date_pattern = '<div class="row">' ~ date_pattern ~ '</div>'|raw %}
{{ date_pattern|replace({
'{{ year }}' : '<div class="col-xs-4">{{ year }}</div>',
'{{ month }}' : '<div class="col-xs-4">{{ month }}</div>',
'{{ day }}' : '<div class="col-xs-4">{{ day }}</div>',
})|raw|replace({
'{{ year }}': form_widget(form.year),
'{{ month }}': form_widget(form.month),
'{{ day }}': form_widget(form.day),
})|raw }}
{% endif %}
{% endblock %}
I also try to override it by using the following code:
Js part:
$(document).ready(function() {
$('.datepicker').datepicker({
format: "DD/MM/YYYY h:mm"
});
});
form part
->add('startTime', DateTimeType::class, [
'required' => true,
'error_bubbling' => false,
'date_widget' => 'single_text',
//<input type="text" class="form-control" data-inputmask-alias="datetime" data-inputmask-inputformat="dd/mm/yyyy" data-mask="" im-insert="false">
// #todo Can we make this format configurable?
'date_format' => 'yyyy-MM-dd', // must match data-date-format as defined in field.html.twig
'minutes' => range(0, 55, 5),
'attr' => ['class' => 'datepicker'],
])
This one overide the actual datepicker, but first doesn't fix the problem(you still have the standard format DD-MM-YYY) then it also broke the js used by the bundle(some navigation button doesn't work etc)
If I found a fix, i will also write the answer here.
So after few work on it and if someone got the same problem, I found one solution, maybe not the best but it's work.
I checked the demo used with adminLte bundle on symfony (Kimai2)
So to be able to edit your calendar and format your date, you need to follow these step:
1 : create a dateTimePickerType and use it instead of default DatetimeType
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DateTimePickerType extends AbstractType
{
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['attr'] = array_merge($view->vars['attr'], [
'data-datetimepicker' => 'on',
'autocomplete' => 'off',
'placeholder' => strtoupper($options['format']),
'data-format' => $options['format_picker'],
'data-time-picker-increment' => $options['time_increment'],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'label' => '',
'widget' => 'single_text',
'html5' => false,
'format' => 'YYYY-MM-DD',
'format_picker' => 'YYYY-MM-DD',
'with_seconds' => false,
'time_increment' => 1,
]);
}
/**
* {#inheritdoc}
*/
public function getParent()
{
return DateTimeType::class;
}
}
and on the formType
->add('startTime', DateTimePickerType::class, [
'required' => true,
'error_bubbling' => false,
'label' => 'startTime',
'format' => "yyyy-MM-dd'T'HH:mm:ss",
'attr' => ['class' => 'js-datepicker-hours'],
])
Then the javascript part, you need to install daterangerpicker from www.daterangepicker.com
and use these following function:
const $ = require('jquery');
global.$ = global.jQuery = $;
const Moment = require('moment');
global.moment = Moment;
require('moment/locale/en-gb');
require('daterangepicker');
$(document).ready(function() {
$('.js-datepicker').daterangepicker({
language: "en",
singleDatePicker: true,
showDropdowns: true,
minYear: 1901,
//maxYear: parseInt(moment().format('YYYY'),10)
});
$('.js-datepicker-hours').daterangepicker({
language: "en",
timePicker: true,
singleDatePicker: true,
showDropdowns: true,
locale: {
format: 'yyyy-MM-DD HH:mm:ss'
}
//maxYear: parseInt(moment().format('YYYY'),10)
});
I'm running Symfony 3.4 LTS and I have an entity Attribute:
<?php
class Attribute
{
private $id;
private $code;
private $value;
private $active;
// My getters and setters
Below the database table:
I would like to get, in a form, all the rows with code == 'productstatus'. I tried:
<?php
$attributes = $this->getDoctrine()->getRepository(Attribute::class)->findBy(['code' => 'productstatus']);
// $attributes contains array with 3 objects 'Attribute'
$form = $this->createFormBuilder($attributes);
$form->add('value', TextType::class);
$output = $form->getForm()->createView();
If I dump() the $output var in Twig:
... I'm unable to make a loop to display the 3 fields with values.
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
Result :
My goal is to allow the user to edit all the values of a specific attributes in the same form (or multiple forms, but in the same page). I already tried with CollectionType without success.
I found a solution: create 2 nested forms and use CollectionType. Hope it helps.
<?php
// Controller
$attributes = $this->getDoctrine()->getRepository(Attribute::class)->findBy(['code' => 'productstatus']);
$form = $this->createForm(AttributeForm::class, ['attributes' => $attributes]);
// AttributeForm
$builder
->add('attributes', CollectionType::class, [
'entry_type' => AttributeValueForm::class,
'allow_add' => true,
'by_reference' => false,
'allow_delete' => true,
]);
// AttributeValueForm
$builder
->add('value', TextType::class, ['label' => false, 'required' => false])
->add('active', CheckboxType::class, ['label' => false, 'required' => false])
// Twig view
{{ form_start(form) }}
{% for attribute in form.attributes.children %}
<tr>
<td>{{ form_widget(attribute.value) }}</td>
<td>{{ form_widget(attribute.active) }}</td>
</tr>
{% endfor %}
{{ form_end(form) }}
You an use an if statement in the your AttributeType like in the example below:
$builder
->add('entree', EntityType::class, array('class'=>'cantineBundle:plat',
'choice_label'=>function($plat){
if($plat->getType()=='Entree'&&$plat->getStatus()=="non reserve"){
return $plat->getNomPlat();
}
},
'multiple'=>false)
);
I have a contact form and I'm trying to put a class to an input of my form.
This is in the ContactType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Contact::class,
]);
}
And this in my twig:
{{ form_start(form) }}
{{ form_widget(form.name, {attr: {class: 'myclass', placeholder: 'name'} }) }}
{{ form_end(form) }}
I get this html:
<input type="text" class="form-control" id="contact_name" name="contact[name]" required="required" placeholder="name">
It's working for placeholder, but not to class. I have tried to put the attr in the builder and it is the same. Is the class form-control overwriting my class? How can I fix it?
I think you're using a bootstrap form theme, check into the config file.
and if the case, you can add this line on the top of your twig file :
{% form_theme form 'form_div_layout.html.twig' %}
Try this if it will help you
{{ form_start(form) }}
{{ form_widget(form.name, {'attr': {'class': 'input-text input-text--white', 'placeholder': 'name'} }) }}
{{ form_end(form) }}
I believe you can't define two attributes on form_wdiget. The way around this is doing both in the FormBuilder or one in the FormBuilder.
You can define attributes on a form element like so:
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'my-class',
],
]);
Note that for a CSS class, it must be in the array attr, not to be confused with a class as in your entity like on the EntityType::class.
Or
$builder
->add('name', TextType::class, [
'placeholder' => 'My place holder',
]);
So you could achieve both like:
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'my-class',
],
'placeholder' => 'My place holder',
]);
You can read more about form field attributes here.
You can read it from the official page:
https://symfony.com/doc/current/reference/forms/types/form.html#attr
Just add: {'attr': {'attribute name': 'value'}}
As shown below
{{ form_widget(form.propertyName, {'attr': {'placeholder': 'name'} }) }}
I am trying to pull in a repository into a form in Symfony 3.4 and then use the chosen option when the form is submitted.
Here's the form code:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('text', TextareaType::class, [
'label' => 'Text'
])
->add('category', EntityType::class, [
'class' => Category::class,
'choice_label' => 'name',
'query_builder' => function(CategoryRepository $repo) {
return $repo->createQueryBuilder('c')
->groupBy('c.name');
}
])
->add('subcategory', EntityType::class, [
'class' => Category::class,
'choice_label' => 'subcategory',
'query_builder' => function(CategoryRepository $repo) {
return $repo->createQueryBuilder('c')
->groupBy('c.subcategory');
}
]);
}
With this I can render the form and it looks good. I can choose the various options in the CategoryRepository.
{% block body %}
{{ form_start(form) }}
{{ form_label(form.name) }}
{{ form_errors(form.name) }}
{{ form_widget(form.name) }}
{{ form_label(form.subcategory) }}
{{ form_errors(form.subcategory) }}
{{ form_widget(form.subcategory) }}
{{ form_end(form) }}
On submit, when checking with Xdebug, the category is the object Category. I can see the correct values present (those chosen in the drop down of the form) but I want just the string, e.g. category.name. How do I do that?
Also, it might need a different question, but when I select one of the categories, I'd like the subcategory to be updated to exclude those that don't belong to that chosen category. I realise this may require jquery.
I'm certain there are better ways, but one solution would be to
$category = $data->getCategory();
$data->setCategory($category->getName());
$data->setSubcategory($category->getSubcategory());
And to exclude the subcategories I use jQuery / JavaScript to retrieve the filtered results from a controller / repository, then remove or add those options in the HTML.
I'm currently creating a Drupal 8 module. I would like to be able to use a custom template to display a select element in a form. Here is the code I have written so far:
File my_module/templates/colorselector.html.twig:
{% spaceless %}
<div class="select-wrapper">
{% set classes = ['form-control', 'color-selector'] %}
<select{{ attributes.addClass(classes) }}>
{% for option in options %}
<option value="{{ option.value }}" data-color="{{ option.code }}"{{ option.selected ? ' selected="selected"' }}>{{ option.label }}</option>
{% endfor %}
</select>
</div>
<script>
$('.color-selector').colorselector();
</script>
{% endspaceless %}
File my_module/my_module.module:
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\RenderElement;
function my_module_theme($existing, $type, $theme, $path) {
return [
// ...
'colorselector' => [
'render element' => 'select'
]
];
}
function my_module_preprocess_colorselector(&$variables) {
$element = $variables['element'];
Element::setAttributes($element, ['id', 'name', 'size']);
RenderElement::setAttributes($element, ['form-select']);
$variables['attributes'] = $element['#attributes'];
$variables['options'] = [];
foreach ($element['#options'] as $colorName => $colorCode) {
$option = [];
$option['value'] = $colorName;
$option['label'] = $colorName;
$option['code'] = $colorCode;
$variables['options'][] = $option;
}
}
File my_module/src/Form/MyCustomForm.php:
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class MyCustomForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state) {
// ...
$form['color'] = [
'#type' => 'select',
'#theme' => 'colorselector',
'#title' => $this->t('Couleur'),
'#required' => TRUE,
'#options' => $options
];
// ...
return $form;
}
// ...
}
I get the following error message when I try to display the form: The website encountered an unexpected error. Please try again later.
If I remove '#theme' => 'colorselector' from $form['color'], it displays the form correctly but it does not use my template obviously.
Do you know where the error comes from and how to fix it?
Thanks!
Your hook_theme function should be like this.
function my_module_theme($existing, $type, $theme, $path) {
return array(
'color_selector' => array(
'variables' => array('params' => null),
'template' => 'colorselector'
)
);
}
Now, your template name might be my_module/templates/colorselector.html.twig