Closed silasjoisten closed 2 years ago
Sounds interesting 😊
I'm not sure how you define the alternative templates? Is this some kind of ChoiceType with predefined options?
No its just a FormType where the User can define its own template and pass twig variables into it. The code looks like the following:
<?php
declare(strict_types=1);
namespace Sonata\AdminBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TemplateType extends AbstractType
{
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['template'] = $options['template'];
$view->vars['options'] = $options['options'];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'template' => null,
'options' => [],
'mapped' => false,
'required' => false,
'label' => false,
]);
}
}
{# src/Resources/views/Form/Type/template.html.twig #}
{% block template_widget %}
{% include form.vars.template with form.vars.options %}
{% endblock %}
<!-- src/Resources/config/form_types.xml -->
<services>
<!-- ... -->
<service id="sonata.admin.form.type.template" class="Sonata\AdminBundle\Form\Type\TemplateType" public="true">
<tag name="form.type" alias="sonata_type_template"/>
</service>
</services>
The User needs todo:
# config/twig.yaml
twig:
form_themes:
- '@SonataAdmin/Form/Type/template.html.twig'
and use the Type like in issue description mentioned.
:thinking: Sorry, but I don't think I like it very much… I mean, what's wrong with overriding a template? Is it too complicated? If yes, maybe that's what we should work on IMO.
Nothings wrong about overriding a template. Was just an idea. I thought in future when there is a redesign of Sonata is it easier to upgrade if there less overritten templates in the world.
I've not been using Sonata for a while, so my question about overriding a template is genuine… if we can make it easier somehow, please consider working on that, but keep in mind that configureFormFields
should be about exactly that: configuring form fields.
I've not been using Sonata for a while, so my question about overriding a template is genuine… if we can make it easier somehow, please consider working on that, but week in mind that
configureFormFields
should be about exactly that: configuring form fields.
In our team, we had to do this a long time ago multiple times. Our strategy was to do a custom Type:
->add('fooCustom', CustomType::class, [
'disabled' => true,
])
The value was provided by a custom getter in the entity
public function fooCustom()
{
return something
}
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class CustomType extends AbstractType
{
/**
* @return mixed
*/
public function getParent()
{
return TextType::class;
}
}
Adding the formTheme
/**
* @return array
*/
public function getFormTheme()
{
return array_merge(
parent::getFormTheme(),
[
'admin/sonata/form/custom.html.twig',
]
);
}
{% block custom_label %}
{% endblock %}
{% block custom_widget %}
Hello world. {{ value }}
{% endblock %}
It's clearly not the best strategy but we were beginners and since it works we always do like this now. If we want to move this custom field on another Admin, or change the order of the field, it feels so much easier in the configure form.
In 4 year using Sonata, we almost never overriding templates. Don't really know why.
@silasjoisten I do like the templateType, this seems similar to our strategy but in a so much better way !
:thinking: :thinking: :thinking: if I try to recall my very old memories of this, I think most of the pain comes from finding the exact name of the block you need to override to achieve your goals… I'd like somebody to show us how overrides are usually done, and if that's cumbersome and can't easily be improved, then maybe we should go with the TemplateType
, especially if it makes the life of everyone easier.
🤔 🤔 🤔 if I try to recall my very old memories of this, I think most of the pain comes from finding the exact name of the block you need to override to achieve your goals… I'd like somebody to show us how overrides are usually done, and if that's cumbersome and can't easily be improved, then maybe we should go with the
TemplateType
, especially if it makes the life of everyone easier.
When we want to override/make something tricky/discover a feature/fix a bug we got deep in the vendor code. We never read the doc because we don't find what we're looking for or we don't know how to find what we're looking for. So in our case, most of the pain is the documentation. I do like the symfony documentation but I don't like the Sonata documentation.
For example, if I want something about the configureForm. I have this https://sonata-project.org/bundles/admin/3-x/doc/getting_started/the_form_view.html this https://sonata-project.org/bundles/admin/3-x/doc/reference/form_types.html this https://sonata-project.org/bundles/admin/3-x/doc/reference/form_help_message.html and many more.
If I want something about the symfony form, i just go here https://symfony.com/doc/current/forms.html
Okay so the docs are shitty, which is not news… is that really the root of the problem here? That no one overrides template because they can't figure out how to do it? Or is it just not possible? Also, the example of @silasjoisten is not a form control, what's the use case for embedding something else than a form inside a form? Did you have similar use cases or were you trying to embed custom form controls?
What about adding a new method to the form builder? ->renderTemplate(template.html.twig, [arguments....])?
I am currently on a phone 📲
Okay so the docs are shitty, which is not news…
I want to be sure that I said that in a constructive way. The Sonata projects are a big help for us. I didn't know that is was an already known fact that the doc was not the best. But making a new one would take a lot of work.
is that really the root of the problem here? That no one overrides template because they can't figure out how to do it? Or is it just not possible?
Can't really help about this point. I would need to see how to do it in order to say which is my preferred way.
what's the use case for embedding something else than a form inside a form? Did you have similar use cases or were you trying to embed custom form controls?
In our society, we created form with some show block
inside.
This display some data you can't edit but you have to see.
For exemple, we have 3 entities: Clients has Contracts which has Vouchers. When I edit a Contract, I want to see all the Vouchers of the Clients in order to check I dont give similar Voucher or too much Voucher.
Plus we have so custom workflow where we are redirect from Entity1 editaction to Entity2 editaction to Entity3 editaction etc.
I want to be sure that I said that in a constructive way. I didn't know that is was an already known fact that the doc was not the best.
Yeah don't worry, I didn't write them ;) I think writing good docs are hard, and I think these docs were not written in one go, but just piled on by many different people, which might explain the feeling of "all over the place" they can give.
Can't really help about this point. I would need to see how to do it in order to say which is my preferred way.
My memories are far, but I think creating a Sonata form results in Twig template blocks, and that those can be overriden. Thanks to the Symfony profiler, you can get a view of the template rendering tree, and find what to override. Might not be as convenient as @silasjoisten 's method.
What about adding a new method to the form builder? ->renderTemplate(template.html.twig, [arguments....])?
That sounds better, because it feels a bit less like twisting a form. In Symfony, forms contain other forms which contain other forms and so on… everything is a form. If we are to add something else, it would be great to make the distinction, and find a name for that something else. So what do you call something that is in a form but is not a form control (some sort of input)?
is that really the root of the problem here? That no one overrides template because they can't figure out how to do it?
Actually, yes, right now its very hard to find the place.
Or is it just not possible? Also, the example of @silasjoisten is not a form control, what's the use case for embedding something else than a form inside a form? Did you have similar use cases or were you trying to embed custom form controls?
For example, i have some forms and the widgets that i need to place between them, that showing the related information for editors.
If we are to add something else, it would be great to make the distinction, and find a name for that something else. So what do you call something that is in a form but is not a form control (some sort of input)?
->appendWidget(string $widgetClass, ?array $options)
or you can use your admin block's logic:
->appendBlock(string $blockClass)
it will force people to write widgets/blocks outside of the controllers or admin configuration.
->appendWidget(ArticlesWithClosestNames::class, ['template' => 'adminShortTemplate.html.twig', widget_options => ['limit' => 10]]);
If we are to add something else, it would be great to make the distinction, and find a name for that something else. So what do you call something that is in a form but is not a form control (some sort of input)?
->appendWidget(string $widgetClass, ?array $options)
or you can use your admin block's logic:->appendBlock(string $blockClass)
it will force people to write widgets/blocks outside of the controllers or admin configuration.
->appendWidget(ArticlesWithClosestNames::class, ['template' => 'adminShortTemplate.html.twig', widget_options => ['limit' => 10]]);
Personnaly I would prefer a more generic function, like the proposed renderTemplate
since it can be use for something else than widget/block.
@silasjoisten Do you want to implement this feature ?
I think it's agreed that the PR will be merged. Maybe there will still a little debate about the name, but that's all. Correct me if I'm wrong @OskarStark @greg0ire
@VincentLanglet sure i will do that but first i finish webpack integration
If we are to add something else, it would be great to make the distinction, and find a name for that something else. So what do you call something that is in a form but is not a form control (some sort of input)?
->appendWidget(string $widgetClass, ?array $options)
or you can use your admin block's logic:->appendBlock(string $blockClass)
it will force people to write widgets/blocks outside of the controllers or admin configuration.->appendWidget(ArticlesWithClosestNames::class, ['template' => 'adminShortTemplate.html.twig', widget_options => ['limit' => 10]]);
Personnaly I would prefer a more generic function, like the proposed
renderTemplate
since it can be use for something else than widget/block.
How about addTemplate? so it would be general.
What about adding a new method to the form builder? ->renderTemplate(template.html.twig, [arguments....])?
That sounds better, because it feels a bit less like twisting a form. In Symfony, forms contain other forms which contain other forms and so on… everything is a form. If we are to add something else, it would be great to make the distinction, and find a name for that something else. So what do you call something that is in a form but is not a form control (some sort of input)?
I discovered virtual_field
: https://symfony.com/doc/master/bundles/SonataAdminBundle/cookbook/recipe_virtual_field.html
With the showMapper, you can write
$showMapper->add('my_custom_field', null, [
'virtual_field' => true,
'template' => 'admin/CRUD/show_my_custom_field.html.twig',
])
Adding the support of this option would be less weird since it would be consistent with other mappers.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I am all the way for a renderTemplate() method which gets a path and parameters
Hi @silasjoisten, this feature would be awesome. Are you still interested to make a PR ? :)
@VincentLanglet yea sure! so wich solution shall i do?
->add('sometemplate', TemplateType:class, ...)
->renderTemplate('path/to/template.html.twig', [] )
virtual_field
After some thoughts
->add('sometemplate', TemplateType:class, ...)
This can be confusing
virtual_field
This still need to use a Type (->add('foo', Type::class, ['virtual_field' => true])
So I think the option 2 ->renderTemplate('path/to/template.html.twig', [] )
is finally the best one.
Yes 👍🏻😃
Friendly ping @silasjoisten, did you have time to take a look for this feature and how to do it because it would be awesome.
Feature Request
I would like to provide a new FormType called
TemplateType
. This allows you to add your custom template into the SonataAdmin configureFormFields without overriding any sonata template.Example
Admin:
Template:
Result:
Without overriding the template.