-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Form] Add position support #11241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Form] Add position support #11241
Conversation
|
||
asort($this->weights, SORT_NUMERIC); | ||
|
||
return array_keys($this->weights); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should reset the properties at the end of the sorting (this will also help with garbage collection by removing the references inside this object)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed the form reference stored in the orderer. For the reset at the end of the ordering, I don't think it is mandatory because all references have been cleaned at this state except if an error is detected during the ordering.
ping @webmozart |
12b7056
to
b1b7c5d
Compare
I have rebased this PR according to the last changes. ping @webmozart |
b1b7c5d
to
d5234b9
Compare
Should I close it and reopen it against the 2.7 branch? |
Sorry for the late reply. I like your work @egeloen! I'm 👍 for this except for a few things:
With these changes and a rebase on 2.8, I'm happy to merge this. :) |
@egeloen Are you still interested in finishing this one? |
It was not clear to me what was the position of the symfony team about this feature. If we all agree, i can indeed finish it :) |
@webmozart said he was ok, so I think we can go ahead and add this feature. |
4b47fcd
to
8b0d12a
Compare
@fabpot @webmozart I have rebased the PR as well as applied your comments. I'm not sure I can add a method to an interface according to the BC promise. Am I allowed? Additionally, the failling build seems unrelated. Anyway, let's review it. |
Adding a method on an interface is not possible. If that makes sense (I haven't reviewed the PR), you can add a new interface. |
* | ||
* @return self The configuration object. | ||
*/ | ||
public function setPosition($position); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, that's not possible as this is a BC break.
@fabpot Okay, so this PR still need some work as I'm adding methods to existing interfaces. @webmozart How would you name this new interface? |
@egeloen Use a semi-random interface name for now so that we can move forward. Renaming it to something won't be that difficult. |
f49722b
to
6a80046
Compare
@fabpot Done |
} | ||
|
||
if (is_string($position) && ($position !== 'first') && ($position !== 'last')) { | ||
throw new InvalidConfigurationException('If you use position as string, you can only use "first" & "last".'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
first or last?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using position as a string, the only supported values are "first" and "last".
/** | ||
* Processes an array position (before/after). | ||
* | ||
* FIXME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still?
Is position option supported for |
Although I agree such a feature would be great, I don't think the implementation should be at the builder level. My guess is that should be done at the Having an order or another only impacts templates, and one could need different orders for different templates. Thus this should not lead to different building processes but different rendering. |
I thinks it should done in all level |
@liverbool In which case do you need an order on submission? If you have dependent fields, you should use listeners to rely either on submitted data ( |
@HeahDude First i'm not Symfony Guru ;) Refer to symfony-cmf/media-bundle#9 Common case check for deletionform:
checkbox: remove_image
image: image_field
addEventListener(): check is remove_image checked
# We need to add addEventListener to every root form that contains image field. My caseform:
checkbox: remove_image
custom_image: image_field
addEventListener(): "can't check is remove_image checked"
# I need to add addEventListener to custom custom_image but i can't get submitted state of remove_image checkbox. My solutionform:
custom_image: image_field # compound field
image: truly_image_field
checkbox: remove_image
addEventListener(): (check is remove_image checked)
addModelTransformer(): (transform truly_image_field to model) My discussioncustom_image: image_field
addEventListener():
- add remove_image to root form by making it's submition fire before custom_image field
- check is remove_image checked when make sure remove_image was submitted first
form:
custom_image: image_field |
@liverbool Let's not mix submission and fields ordering. I really think that a submission depending on the fields order is very fragile. The solution you wrote is the way to go: a custom type with a specific needs so with event listeners, data transformers and data mappers when useful. |
@HeahDude I agree order submission |
I'm a bit late to the party. Sorry. One could argue that field order is presentation logic. Outside of their presentation, field order doesn't really matter to a form. HTTP doesn't care, relational databases don't generally care. Can't comment about nosql, perhaps field order is a concern there. With that in mind, perhaps having field ordering in the form is not the way to go. A mechanism for sorting children within FormViews seems a little more abstracted.
This will probably be very simple to implement as it's just an array manipulation. It also allows one to easily specify the sorting in a template:
Seems more MVC to keep presentation logic in the view, and it might not cause any BC breaks. |
Adding this method to
There's probably a nicer way to write the code. But it works.
Or in twig:
|
I agree with @henrypenny that this is a presentation logic issue and should not be implemented in terms of {% form_order my_form [ 'field1', 'field2', 'field3' ] %}
{{ form(my_form) }} vs {% form_order my_form [ 'field1', 'field2', 'field3' ] %}
{{ form_start(my_form) }}
{{ form_widget(my_form) }}
{{ form_end(my_form) }} vs {{ form_start(my_form) }}
{{ form_errors(my_form) }}
{{ form_row(my_form.field1) }}
{{ form_row(my_form.field2) }}
{{ form_row(my_form.field3) }}
{{ form_end(my_form) }} Only the first example is significantly smaller, than the others, while also being the simplest. As soon as you start dealing with compound subforms and want to interleave their output |
Closing this old PR as it does not seem that there is a consensus. Having order only at the template level seems like the best way to go. |
This PR was squashed before being merged into the 5.3-dev branch. Discussion ---------- [Form] Add support for sorting fields | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #5827 | License | MIT | Doc PR | TODO This PR adds a new `priority` option used later to sort all fields in order of importance instead of simply numerical order, i.e. fields with higher priority will be rendered first, fields with lower priority will be rendered last. The default priority would be "0" for all fields. Fields with equal priority will keep the original order (stable sorting). History of previous proposals and discussions: #3452, #4254, #5827, #6111, #11241 This kind of feature has been abandoned in the past because complex proposals, and somehow rejected because ideally we should do the sorting at the view level ([customizing form](https://symfony.com/doc/current/form/form_customization.html) themes or layout templates) and it's true for most cases (the simple ones I think) but the fact is that it's often quite complex to accomplish that way, mainly for [dynamic forms](https://symfony.com/doc/current/form/dynamic_form_modification.html). Let's focus the following analysis on explaining *why* and *when* the `priority` option could save us a lot of time, getting rid of cumbersome workarounds with templates to change the rendering order *only*. --- A common example could be the building of a multi-steps form with a convenient type hierarchy and including fields dynamically based on the data. Let's take this sample:  ```php class WorkflowType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { // get current enabled transitions from the workflow definition... foreach ($enabledTransitions as $transitionName) { $builder->add($transitionName, SubmitType::class, ['attr' => ['value' => $transitionName]]); } } } class PersonRegistrationType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('firstName') ->add('lastName'); $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { $person = $event->getData(); if ($person->isLegalType()) { $event->getForm()->add('company'); } }); } public function getParent() { return WorkflowType::class; } } ``` These classes model the required form. However, according to the form building process and taken into account that the underlaying person data was set with "legal" type (from the previous step), this will be the rendering result: ```html <button type="submit" name="form[register]" value="register">Register</button> {# wrong place #} <input name="form[first_name]"> <input name="form[last_name]"> <input name="form[company]"> {# wrong place #} ``` Now, taking the view customization path to fix the order, you likely will face some problems regarding to: - How do I render the dynamic submit buttons at the bottom? - How can the specific form fields be rendered in the correct order if they vary from step to step? (being it a generic template) - if you solve the previous questions, you will also need to check if the company field is defined or not before rendering it in the right order. There could be more and different problems depending on the context and you can find workarounds using the block prefixes system to customize each step block theme, but to me it's enough to think about other alternatives. On the other side, using the `priority` option, the solution is quite easy. Setting the right priority value will guarantee the right rendering order: ```php // ... $builder->add($transitionName, SubmitType::class, ['priority' => -1, // ...]); // ... $event->getForm()->add('company', null, ['priority' => 1]); ``` That's ! There is no need to customize templates at all when you only need to change the fields order. This way, these fields are being pre-defined in the order they will be rendered at view level. This sorting process will take place on `$form->createView()` method, just after `buildView()` and before `finishView()` calls. Could we reconsider the usefulness of this feature? please. Cheers! Commits ------- 62650bb [Form] Add support for sorting fields
This PR migrates egeloen/ivory-ordered-form into the core. It implements the feature the way @webmozart has explained in #5827. The UPGRADE file needs some love according to the BC promise but first, I would like some feedback :)