Problem
When creating a new form (through Contact Forms), the user can define the form display and view display. Both are working fine when viewing a form or a submission (using the Contact Messages module). However, when the visitor clicks on preview before submitting, the preview shows the individual form field values in an apparently random order.
Inspecting the HTML, it seems, all previewed fields are sorted by their machine name. I am not sure, how the preview is built, in MessageForm.php it says
$form['preview']['message'] = $this->entityManager->getViewBuilder('contact_message')->view($message, 'full');
but I can't find the correct implementation of that function to take a look.
I think, the correct viewBuilder is in the Contact Storage module which is currently Third-Party but seems to be on its way to become part of Drupal 8.3.x (see #2750629: Add view builder for contact module's Message entity). Then I get lost where to look next in order to change the sorting to use weights.
| Comment | File | Size | Author |
|---|---|---|---|
| #38 | after.png | 42.75 KB | shivam_tiwari |
| #38 | before.png | 42.43 KB | shivam_tiwari |
| #34 | render-preview-2833096.patch | 754 bytes | nmudgal |
| #33 | form-display-weights-d10.patch | 3.12 KB | ruuds |
| #26 | interdiff.txt | 427 bytes | kapilv |
Issue fork drupal-2833096
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
berdirMoving to contact.module, which probably simply needs to expose preview as an extra field to fix this in contact_entity_extra_field_info()
Comment #3
berdirAnd I knew I've seen this before: #1867030: Contact message preview appears at random form position after sorting fields in Manage fields
Comment #4
broonSorry, but I disagree with this being a duplicate. The linked issue is about the position of the preview in the form (as in having the preview as a whole above or below the form). My issue is that the individual values inside the preview are in wrong order. For example, assume you have two fields in your form: (1) Field 1, name "username", weight -10 and (2) Field 2, name "age", weight 0.
With the weight, the form will show the fields in the order [username, age]. However, if you click preview, the order will be [age, username] as the fields are sorted by machine name instead of the field's weight.
Comment #5
berdirwhich weight, the form or the view display weight?
View respects the *view* weights.
Comment #6
broonNeither weight is respected in the preview.
By setting the form display weight, I can arrange fields within the form (working, see below the order of the fields in the form: [username, age]). I also have the same order set up on the view display page.
But when the user hits the "Preview" button, the fields within the preview do not have the same order as the fields in the form, they are in order [age, username].
Comment #7
berdirThat screenshot is the form display, what's your formatter configuration?
Comment #8
broonFormatter configuration for what? The Preview "field" has no formatter options. Are you talking about the "Manage display" tab? It has no effect here afaik, but as said above it has the same order.
Comment #9
berdirYes, I'm talking about "Manage display". That's exactly what *should* affect that order, and based on your explanations I wasn't sure if that was clear to you.
Based on your feedback, tried it myself and can confirm that problem now. It's a fun conflict between the form system (which has some logic to avoid sorting elements with elements that have no children with an explicit #weight in FormBuilder::doBuildForm()) and the entity render cache process (which pre-creates empty render arrays with just a #pre_render, that then get marked as #sorted). Combined with the fact that most entity types actually have a preprocess where they copy all rendered fields into a new structure and drop any properties set on the container, like #sorted and are therefore not affected by this.
Here's a dirty fix, we probably want something deeper in the renderer, for example something that unsets #sorted if we run a #pre_render or similar function that might add/change elements and their weight.
Comment #10
tstoecklerWow, I've actually hit this before, too, but didn't realize it was due to the
#sortedthing, that's amazing!Comment #11
broonThanks for debugging the problem, sometimes it's just a single line. ;) Good job!
It works for me now but I am not deep enough into D8 core to actually RBTC this and as you said, this might have some implications on other behaviour.
Comment #12
berdiryeah, this is not meant to be committed, we need tests and likely a very different fix.
It would actually also conflict with #2756689: Label of contact form message field is not hidden as that issue removes the whole method.
Comment #13
wim leersGreat find :)
This would need a comment for sure :)
Comment #14
berdirComment #24
ruuds commentedThe patch of #9 doesn't work on 8.9.x anymore. I solved the problem by rendering the preview message as markup. It seems the form rendering interferences with the rendering of the nested contact message preview.
See the attached patch.
Comment #25
kapilv commentedComment #26
kapilv commentedfixed Custom Commands Failed.
Comment #30
smustgrave commentedFor tests requested in #12
Comment #32
andypostComment #33
ruuds commentedThe previous patch didn't apply to Drupal 10, so i've updated it.
Comment #34
nmudgal commentedUsing #markup bypasses field formatters, caching, and theming, leading to inflexible, inconsistent, and unmaintainable output. As per Berdir's comment, overriding buildMultiple in the MessageViewBuilder and explicitly unsetting #sorted resolves the issue.
Just attaching the patch for now (Please validate if this is the right approach/place)
Comment #35
smustgrave commentedHave not reviewed but was previously tagged for tests and fixes should be in MRs vs patches
Comment #36
shivam_tiwari commentedI am working on this issue.
Comment #38
shivam_tiwari commentedI verified code and created MR for this. Attached the screenshots related to my testing.
Comment #39
shivam_tiwari commentedComment #40
smustgrave commentedStill needs test coverage
Comment #41
quietone commentedThe Contact Module was approved for removal in #3476879: [Policy] Move Contact module to contrib.
This is Postponed. The status is set according to two policies. The Remove a core extension and move it to a contributed project and the Extensions approved for removal policies.
The deprecation work is in #3520460: [meta] Tasks to deprecate the Contact module and the removal work in #3520466: [meta] Tasks to remove Contact module.
Contact will be moved to a contributed project after the Drupal 12.x branch is open.
Comment #43
andypost