Categories
Web Development

Symfony 5+ how to make a form field hidden from display

This is easier than it sounds, but I am writing this in case I need to remember what the answer is.

At first I wasn’t paying attention to all of the many different Symfony form types in this long list.  I totally didn’t see the HiddenType in the list or I didn’t notice it.

I tried to simply add a class using attr in the definition. This kind of worked. It just showed the name of the field in a label, which wouldn’t work for my design and use.

HiddenType works exactly like what I needed.

When building a form in a FormType class you can create hidden fields like this one which hides a nonce for AJAX request validation.

->add('ajaxString', HiddenType::class, [
    'mapped' => false,
    'attr' => ['class' => 'hidden-field', 'value' => $secretString]
])

Always add ‘mapped’ false for any field you want to tell Symfony to ignore, like this field used for processing AJAX requests. $secretString is just a random 32 character string I am storing in a session on the backend and sending with the AJAX request to make sure the request is coming from my app.

Categories
Web Development

How to change the id for a form input in Symfony 5+

If you create your forms with classes in Symfony 5+ then changing the ID of the form fields is something you are not allowed to do apparently. LOL You can add/change the class and other attributes but not the id. For some reason Symfony ONLY lets you change the id inside the template. I don’t know why.

Yes I am serious

To start with what got me even interested in trying to use attr and row_attr is when I was messing around with some of my forms, I was copying and pasting and moving parts in the template. This lead to issues as I would miss pieces or get things wrong some how. So I started trying to do the whole thing inside the FormType definition class using the methods below.

It has been pointed out that some feel it is better to define class, id etc. in the template. But as I pointed out above, I had issues with that. So below is what I found.

What doesn’t work

If you are like me then you have probably tried changing the ID by using the attr or row_attr attributes of the Type right? That seems logical right?

These two methods  are not even consistent. First off row_attr only accepts some attributes, which ones I have no idea, it ignores placeholder and id apparently. So then I tried attr, it works with placeholder but ignores ID.

Makes sense right?

It sure would be nice if those didn’t ignore the values you sent to them wouldn’t it. This problem is nearly 10 years old. Later I may look over the code update it and do a PR.

If you are like me you are using Javascript to read hidden fields from the form for various reasons. Otherwise the standard naming of ID’s works flawlessly. I had not discovered this until I had this unique use case.

What does work

So it appears the only way to do this is inconsistentYou have to do it in the form rendering code inside the template. Like this

{{ form_row(registrationForm.ajaxString, { 'id': 'ajaxString'}) }}

You can also change/add other attributes this way, but you can ONLY CHANGE THE ID THIS WAY.

Otherwise Symfony takes it upon itself to name the field for you and ignore your request.

Dictating like…

It would be much easier and consistent if I could just add the ID in the FormType definition class instead of having to add it to the template. Class and other attributes can be added/changed like this, but not id. Just a little confusing that is all.

Categories
Web Development

How to add placeholder text to a Symfony 5+ form row

If you are using the Symfony forms system, which I assume you are if you are here, then this post is for you. Otherwise you figure it out. LOL

you need to figure it out meme
This is only for symfony forms otherwise…

There is more than one way to do this. However, I am going to show the way I prefer and that is right in the form type definition class.

When you build a form by way of creating a form type class, then it is easy to set all of the options and values you need in one location..

By looking at the documentation one would think the following would work for the HTML placeholder attribute


->add('userAlias', TextType::class, [
            'mapped' => false,
            'constraints' => new Length([
                'min' => 2,
                // max length allowed by Symfony for security reasons
                'max' => $userAliasObj->getColumnLength(UserAliasTable::ALIAS)
            ]),
            'row_attr' => ['placeholder' => $this->aliasPlaceholder]
        ])

BUT …. SURPRISE IT DOESN’T WORK. Why? Who knows? Docs need updating, something changed? We might never know.

It even says the following in the docs for row_attr

An associative array of the HTML attributes added to the element which is used to render the form type row:

Uhm, wait… what?

I am guessing all of the other HTML attributes will work with row_attr? Maybe they do not consider the placeholder attribute as an attribute?

 

However, I did discover that plain “attr” works with the placeholder attribute like so.


->add('userAlias', TextType::class, [
            'mapped' => false,
            'constraints' => new Length([
                'min' => 2,
                // max length allowed by Symfony for security reasons
                'max' => $userAliasObj->getColumnLength(UserAliasTable::ALIAS)
            ]),
            'attr' => ['placeholder' => $this->aliasPlaceholder]
        ])

The docs say the following about attr

If you want to add extra attributes to an HTML field representation you can use the attr option. It’s an associative array with HTML attributes as keys. This can be useful when you need to set a custom class for some widget:

Dear Symfony, placeholder is not an extra attribute it is a valid html attribute.

symfony meme
Say what?

Keeping things together

better together meme
Keeping your form pieces together is better later.

Keeping all of the form related stuff in one location makes it easier to find and make changes. Some people may argue that you should do this in the template so that non programmers can make changes. I argue if you can learn HTML you can learn to read the docs and articles like this and figure it out. LOL

The interesting thing is the field definitions in your FormType class do not have to be in the order you want them displayed in the browser. This is actually done in the template. This makes it easy to move the small pieces around by copy and paste and it means you get much fewer html bugs. That is another reason I argue if you hire someone who knows only html they should learn this simple system.

My FormType definition for the registration form, for my app contains quite a few fields. However, I can quickly redesign it with confidence by moving a line or two of code instead of hundreds of lines.


{{ form_row(registrationForm.userAlias) }}
        {{ form_start(registrationForm) }}
        {{ form_errors(registrationForm) }}
        {{ form_row(registrationForm.email) }}
        {{ form_row(registrationForm.emailMatch) }}
        {{ form_row(registrationForm.plainPassword) }}
        {{ form_row(registrationForm.passwordMatch) }}
        {{ form_row(registrationForm.agreeTerms) }}

See how making changes to the forms layout is super easy this way.

symfony forms meme
Symfony forms made easy.