ViewsForm::getFormId() constructs the form id from the view name and the display id.
If a view is repeated on the same page with different arguments (showing different cart orders in my case), the forms will clash cause the form id is the same.

Proposed solution:
DisplayPluginBase::elementPreRender() should pass $view->args to ViewsForm::create().
ViewsForm should store the arguments and use them in getFormId().
If there are no arguments, the logic stays the same, if there are arguments, we concat them and create a short hash.

Comments

bojanz created an issue. See original summary.

bojanz’s picture

Status: Active » Needs review
StatusFileSize
new3.33 KB

This patch fixes the issue. It received a sanity check by dawehner. Needs tests.

dawehner’s picture

Issue tags: +Needs tests

Let's ensure we won't forget tests ...

bojanz’s picture

Test plan:
Implement a dummy views form handler which outputs a button, which when clicked outputs a message containing the first views argument.
Create a view that accepts an argument and contains the button handler.
Embed the view twice.
Ensure that clicking the button on the second view gives the correct message (instead of activating the first view).

vasike’s picture

StatusFileSize
new13.41 KB

There is an update of the patch using Bojan's suggestions
adding some code for testing
- New Views form field plugin/hanlder
- New test view to be used, it uses this Views form field and Global null argument (fixed)
- New Route for the testing page using:
- New controller to build page with the defined view embeded twice
- New Views test to operate on the page built - incomplete.

It seems there is an issue to have Views forms in the page - the page is built without forms - content only.
So it needs work.
Maybe we need to update also the issue status.

mglaman’s picture

StatusFileSize
new9.12 KB

Here's an interdiff between #1 and #5.

dawehner’s picture

  1. +++ b/core/modules/views/src/Form/ViewsForm.php
    @@ -66,6 +66,13 @@ class ViewsForm implements FormInterface, ContainerInjectionInterface {
    +  protected $viewArgs;
    

    Is it just me that $view_args instead of $view_arguments is a bit annoying?

  2. +++ b/core/modules/views/tests/modules/views_test_data/src/Controller/ViewsTestFormMultipleController.php
    @@ -0,0 +1,44 @@
    +  public function testPage() {
    +    $build = [
    +      'view_arg1' => [
    +        '#prefix' => '<div class="view-test-form-multiple-1">',
    +        '#suffix' => '</div>',
    +        '#type' => 'view',
    +        '#name' => 'test_form_multiple',
    +        '#display_id' => 'default',
    +        '#arguments' => ['arg1'],
    +        '#embed' => TRUE,
    +      ],
    +      'view_arg2' => [
    +        '#prefix' => '<div class="view-test-form-multiple-2">',
    +        '#suffix' => '</div>',
    +        '#type' => 'view',
    +        '#name' => 'test_form_multiple',
    +        '#display_id' => 'default',
    +        '#arguments' => ['arg2'],
    +        '#embed' => TRUE,
    +      ],
    +    ];
    

    I'm curious whether we should just go with twice the same block on the same page? This would save a bunch of the code here

mglaman’s picture

Assigned: Unassigned » mglaman

Working on this. Looks like we were missing the following from the test, so that the custom field plugin is discovered

  /**
   * {@inheritdoc}
   */
  protected function viewsData() {
    $data = parent::viewsData();
    $data['views_test_data']['job']['field']['id'] = 'field_form_button_test';
    $data['views_test_data']['job']['field']['click sortable'] = FALSE;
    $data['views_test_data']['id']['field']['click sortable'] = TRUE;
    return $data;
  }
mglaman’s picture

The view is now rendering the test buttons on each row and a save button for each view. Just need to write interactions.

Status: Needs review » Needs work

The last submitted patch, 9: views_forms_can_t_be-2644598-9.patch, failed testing.

mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new2.63 KB
new14.27 KB

Here we go, test now runs and ensures each submit button runs its appropriate form.

mglaman’s picture

Assigned: mglaman » Unassigned
mglaman’s picture

Assigned: Unassigned » mglaman
Issue tags: -Needs tests

Per #7, going to rename variable and instead of using custom page, place as blocks on homepage.

vasike’s picture

Status: Needs review » Needs work

@mglaman i can confirm that the #11 patch works.
But the "confirmation" text should be the message provided by the button submission not a custom text.

mglaman’s picture

But the "confirmation" text should be the message provided by the button submission not a custom text.

Could you elaborate? It is checking the message set by the button. The message says the view ID, display, and the row index. We then check for that.

Currently simpletest, as far as I could see, only allows specifying a form ID and not specific button. I added row index so we could hopefully actually test that in future.

mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new14.29 KB
new1.13 KB

dawehner, I started working on placing the blocks. However, it doesn't seem we can pass view arguments through a block's settings, only the items per page. I've left the page controller as it is since the block option does not seem feasible yet.

bojanz’s picture

Agreed, keep the page. +1 to RTBC.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

dawehner, I started working on placing the blocks. However, it doesn't seem we can pass view arguments through a block's settings, only the items per page. I've left the page controller as it is since the block option does not seem feasible yet.

Fair point.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 16: views_forms_can_t_be-2644598-16.patch, failed testing.

mglaman’s picture

Status: Needs work » Reviewed & tested by the community

? Bot says test fail but results show different ¿

catch’s picture

Version: 8.0.x-dev » 8.1.x-dev
Issue tags: +Needs change record

This needs a change record for the constructor change to ViewsForm.

While it's a genuine bug fix, it's changing some @internal API surface, so moving to 8.1.x first. If this is blocking a stable Drupal Commerce release we'll need to think about a patch-release-safe way to do it in 8.0.x.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 16: views_forms_can_t_be-2644598-16.patch, failed testing.

catch’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs change record

@bojanz pinged me in irc. In this case we don't expect anyone to call the constructor directly or override - this isn't a service. So we shouldn't do a change record because it's not something we're expecting people to have to update for. However the theoretical chance that someone might means it's still a default 8.1.x-only change unless we really, really can't wait (and then we might need to change the patch a bit).

alexpott’s picture

Aren't form IDs changing doesn't this mean that potential custom code that altered one of this forms would have to change? Is that not worth a CR?

catch’s picture

Status: Reviewed & tested by the community » Needs work

That's a good point.

Also it's a bit worse than that - hook_form_FORM_ID_alter() would have been usable before, but won't be now because the arguments change. Unless we can somehow make hook_form_BASE_FORM_ID_alter() work but this isn't using hook_forms() at all.

mglaman’s picture

I'll work on the CR as noted in #24.

In regards to #25, I'll see how we can preserve the original form ID for hook_form_BASE_FORM_ID_alter . We just need to stuff it into the build info.

From \Drupal\Core\Form\FormBuilderInterface::prepareForm()

    // Invoke hook_form_alter(), hook_form_BASE_FORM_ID_alter(), and
    // hook_form_FORM_ID_alter() implementations.
    $hooks = array('form');
    if (isset($build_info['base_form_id'])) {
      $hooks[] = 'form_' . $build_info['base_form_id'];
    }
    $hooks[] = 'form_' . $form_id;

EDIT: By adding the form ID without arguments (as it is now) in the base form ID, no existing code should be broken.

mglaman’s picture

Here is an updated patch. This adds a base form ID so that existing hooks work as expected, but the form ID is unique based on arguements.

Here is change record draft: https://www.drupal.org/node/2664936

mglaman’s picture

Status: Needs work » Needs review

Arg, forgot to change status!

bojanz’s picture

Status: Needs review » Reviewed & tested by the community

Great job!

tim.plunkett’s picture

Don't we need tests for that last change, and to ensure it fixes #25?

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Yes I think we do, that would have been a proper API break and we very nearly missed it.

mglaman’s picture

Assigned: mglaman » Unassigned
Status: Needs work » Needs review
StatusFileSize
new409.39 KB
new1.5 KB

Here is a test that addresses #30 and #31

Status: Needs review » Needs work

The last submitted patch, 32: views_forms_can_t_be-2644598-32.patch, failed testing.

mglaman’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new15.8 KB

Not sure what I did to roll such a borked patch. Here is proper one.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thanks a lot. We now have a test to ensure we don't break existing hook_form_alter() implementations.

  • catch committed 6325f60 on 8.1.x
    Issue #2644598 by mglaman, bojanz, vasike: Views forms can't be used...
catch’s picture

Status: Reviewed & tested by the community » Fixed

That's great. Committed/pushed to 8.1.x, thanks!

bojanz’s picture

Version: 8.1.x-dev » 8.0.x-dev
Status: Fixed » Reviewed & tested by the community

I feel that this fix is safe for 8.0.x as well, especially now that the base form id is kept the same.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 34: views_forms_can_t_be-2644598-34.patch, failed testing.

bojanz’s picture

Version: 8.0.x-dev » 8.1.x-dev
Status: Needs work » Fixed

8.1 is in beta, so pushing this into 8.0 doesn't really matter anymore.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

quietone’s picture

published change record.