Problem/Motivation

One annoyance with the "out-of-the-box" experience when creating new entity types is the lack of redirects from add, edit and delete forms.

Implementing a redirect in the form class itself is possible, but different entity types might redirect to different routes. Nodes, for example, redirect to the canonical node types redirect to the collection route.

Proposed resolution

If there is a collection route with a list builder, most likely the user wants to return to the list after editing or deleting an entity, regardless of where that form would otherwise redirect.

Thus, let's add a destination query parameter to the disable, edit and delete links in the list builder.

This is already done explicitly, for example, in the node listing, so is an established pattern.

Remaining tasks

User interface changes

The operation links of list builders will include destination query parameters so that the user is redirected back to the list builder after performing the operation. In core this should not affect anything because we already have explicit redirects in all of the form classes.

API changes

None.

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tstoeckler created an issue. See original summary.

tstoeckler’s picture

Status: Active » Needs review
FileSize
927 bytes

Here we go.

The slight downside of this is that it couples the list builder to the collection route which it otherwise does not know about, but IMO the benefits of this outweigh that.

Status: Needs review » Needs work

The last submitted patch, 2: 2767857-list-builder-destination.patch, failed testing.

tstoeckler’s picture

Assigned: Unassigned » tstoeckler

I also thought about making this a separate class which extends the default EntityListBuilder but I plan to add another list builder which shows the label and that almost certainly will have to be a separate class as that will break existing stuff if we make it the default. So, that would be problematic, so trying to see if we can get away with this. All test fails up to UpdatePathWithBrokenRoutingFilledTest and DefaultViewsTest are test only, so so far so good. I haven't figured out those two yet.

tstoeckler’s picture

Assigned: tstoeckler » Unassigned

Ahh OK, the first one is #2749955: Random fails in UpdatePathTestBase tests.

The views one points to a problem, though: The "Duplicate" action in Views UI should not redirect to the collection, but to the new, duplicated view. So I guess we really can't get away with this at least not in its current form. Another idea would be to only add the destination for edit and delete operations, but that could also lead to inconsistent behavior. Hmm....

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
3.07 KB

Due to #5, I don't think this will fly. So hi-jacking this issue.

Instead I think we should add a completely new list builder, which 1. adds a label column and 2. also includes the destination in the links. That would still be a huge win for DX and we could consider moving some list builders over to that as a follow-up.

Another annoying bit is that we have ConfigEntityListBuilder, so if we make this generic (i.e. available also to content entities) then config entities are pretty much out of the picture because their list builders all extend that.

Anyway, here is something I had lying around locally.

tstoeckler’s picture

Title: Add a destination to operation links in the entity list builder » Add a list builder with a label and destination query parameters in operation links
Issue tags: +Needs issue summary update
Berdir’s picture

Berdir’s picture

Status: Needs review » Needs work

As commented in that issue, we need to use the redirect destination trait instead so it works with custom views pages and so on as well.

My recommendation would actually be to simply add the destination explicitly to the default edit and delete links and not all of them.

Simple example where a destination IMHO doesn't make sense is for examplethe field_ui links, I don't think those should return back and it might result in strange behavior on those forms. If we add it to the default edit/delete links then we cover the 80% use case and can IMHO even do so by default, without a new class, so that everyone benefits from it.

That's also consistent with the logic in \Drupal\node\NodeListBuilder::getDefaultOperations(), with what I'm doing in #2838968: BlockContentListBuilder should use RedirectDestinationTrait instead of hardcoding the collection link template as well as the one added in #2469567: Entity operations for terms are hardcoded in taxonomy terms's overview page.

Berdir’s picture

Status: Needs work » Needs review
FileSize
6.06 KB

This is what I had in mind.

Status: Needs review » Needs work

The last submitted patch, 11: 2767857-list-builder-destination-11.patch, failed testing.

tstoeckler’s picture

Title: Add a list builder with a label and destination query parameters in operation links » Add destination to edit, delete, enable, disable links in entity list builders

I like that approach a lot, I it makes sense. I have only one super, super minor thing:

+++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php
@@ -250,4 +254,22 @@ protected function getTitle() {
+    $query = (array) $url->getOption('query');

Super nitpick, but the cast is only relevant if the option is not there, right? If so, I would find ?: [] a bit clearer.

tstoeckler’s picture

Issue summary: View changes
Berdir’s picture

Ha, ConfigurationTest in action.module was fun. Already ported to BrowserTestBase but still thinking like Drupal 7 where aid's where a thing and was a number that had to be parsed out of a URL. That regex also catched the ?destination that's now part of the URL and it resulted in a completely messed up URL. Which is not needed anyway, as we already click on the Delete link and already are on that page.

Simplifed that test.

Same story for \Drupal\node\Tests\NodeActionsConfigurationTest.

And some other fixes, didn't fix the views test yet, as I'm not sure what to do about this. This basically means that the destination can't be disabled unless views explicitly *removes* the destination key and I'm not sure why that would be useful, honestly.

About the (array) thing, mergeOptions() actually landed a few days ago, which makes this way simpler, even wondering to drop ensureDestination() again and just call this directly.

tstoeckler’s picture

On mergeOptions(): I was thinking about that too, but AFAIK this will now overwrite a pre-existing destination query, whereas the previous patch did not. I may be missing something, though...

Otherwise looks great.

Yeah, the Views thing is sad. Maybe we can get away with removing that setting altogether? @Xano will be sad about that, but maybe I can appease him when I visit on the weekend... With this are there any legitimate uses of this setting assuming it would work?

Berdir’s picture

That's true, but not sure if that's really a problem, afaik only it would already be returned by toUrl(), which seems pretty unlikely?

About the views setting, not sure. It might still affect some other operations but the question is if you'd want those to have a destination anyway?

Happy to hear use cases from Xano if he thinks that there is a reason. *Adding* that option made sense, as you wouldn't have wanted to not have those destinations. I see little reason to not have them, especially as we've now also fixed some related bugs with e.g. node preview. And as mentioned, the setting already didn't work for nodes, which is probably still the 80% use case for creating views with operation links...

Status: Needs review » Needs work

The last submitted patch, 15: 2767857-list-builder-destination-15.patch, failed testing.

dagmar’s picture

Somewhat related #2668794: RedirectDestination:get doesn't use proper query parameters the same issue with the destination parameter exists for admin listings.

dagmar’s picture

Somewhat related #2668794: RedirectDestination:get doesn't use proper query parameters the same issue with the destination parameter exists for admin listings.

dawehner’s picture

One annoyance with the "out-of-the-box" experience when creating new entity types is the lack of redirects from add, edit and delete forms.

Yeah these are the "small" things which sum up as being annoying. Having them fixed is just great.

On mergeOptions(): I was thinking about that too, but AFAIK this will now overwrite a pre-existing destination query, whereas the previous patch did not. I may be missing something, though...

That's true, but not sure if that's really a problem, afaik only it would already be returned by toUrl(), which seems pretty unlikely?

I believe this is actually a fair price to pay. Especially when people really care, they could still implement their own list builder and override it there again.

About the views setting, not sure. It might still affect some other operations but the question is if you'd want those to have a destination anyway?

I'm pretty sure this option wasn't added 100% on purpose but rather this was about having some kind of parity with \Drupal\views\Plugin\views\field\Links

All in all I would be personally be fine with +1 on removing the option from views.

Berdir’s picture

Not every operation and not every entity type will include a destination. For example translate will not and I think that actually makes sense, as the 90% use case there is to go to another page and e.g. the Add/Edit buttons there lose the destination anyway.

What about adding a description to that setting that says something like: "Force a destination for every operation. Many operations will already include the correct destination, it is recommended to have this disabled unless needed." Or maybe even put a "Deprecated:" prefix in front of it?

And then figure out what to do about the tests :)

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Berdir’s picture

Reroll for now.

Status: Needs review » Needs work

The last submitted patch, 24: 2767857-list-builder-destination-24.patch, failed testing. View results

Berdir’s picture

The views test was actually just broken because it uses string concatenation and ended up with URL?destination=/?destination=... ;)

Implemented my suggestion from above with the updated description. also disabled the setting by default. Wondering if and what that is going to break.

dawehner’s picture

Issue summary: View changes
+++ b/core/modules/filter/src/Tests/FilterAdminTest.php
@@ -135,16 +136,9 @@ public function testFormatAdmin() {
-    // Cannot use the assertNoLinkByHref method as it does partial url matching
-    // and 'admin/config/content/formats/manage/' . $format_id . '/disable'
-    // exists.
-    // @todo: See https://www.drupal.org/node/2031223 for the above.
-    $edit_link = $this->xpath('//a[@href=:href]', [
-      ':href' => \Drupal::url('entity.filter_format.edit_form', ['filter_format' => $format_id])
-    ]);
-    $this->assertTrue($edit_link, format_string('Link href %href found.',
-      ['%href' => 'admin/config/content/formats/manage/' . $format_id]
-    ));
+    $destination = Url::fromRoute('filter.admin_overview')->toString();
+    $edit_href = Url::fromRoute('entity.filter_format.edit_form', ['filter_format' => $format_id], ['query' => ['destination' => $destination]])->toString();
+    $this->assertLinkByHref($edit_href);

This is some nice improvement

Berdir’s picture

Yeah, with the destination, the links are now unique and we longer need the custom asserts.

However, I was a bit confused with that comment because it says assertNoLinkByHref(), but we actually assert that there is one.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

LGTM!

+++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php
@@ -250,4 +254,17 @@ protected function getTitle() {
+   *   The URL object.

Nit: "The updated URL object."

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

No longer applies

+++ b/core/modules/node/src/NodeListBuilder.php
@@ -41,14 +33,11 @@ class NodeListBuilder extends EntityListBuilder {
-   * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
-   *   The redirect destination service.
    */
-  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) {
+  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter) {
     parent::__construct($entity_type, $storage);
 
     $this->dateFormatter = $date_formatter;
-    $this->redirectDestination = $redirect_destination;

@@ -58,8 +47,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
-      $container->get('date.formatter'),
-      $container->get('redirect.destination')
+      $container->get('date.formatter')

This change is unnecessary in my book.

Yes, we can get it from the trait, but that doesn't preclude injecting it properly.

And removing this change makes the patch less disruptive.

but +1 on this change

Berdir’s picture

Rerolled and restored the constructor argument in NodeListBuilder, fine with keeping that.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
larowlan’s picture

+++ b/core/modules/views/src/Plugin/views/field/EntityOperations.php
@@ -99,7 +99,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+      ... Most operations include a destination by default and this setting is not longer needed ...

Not longer needed => No longer needed, can be fixed on commit

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: -Needs issue summary update +Needs change record

Can we get a change record here - thanks - there would be lots of contrib modules that can benefit from this

Berdir’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Manually tested, works like it says on the box.

Committed as 401bd66 and pushed to 8.5.x. Thanks! >

Published change record.

  • larowlan committed 401bd66 on 8.5.x
    Issue #2767857 by Berdir, tstoeckler: Add destination to edit, delete,...

Status: Fixed » Closed (fixed)

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

oxrc’s picture

Re-rolled the patch from #32 to apply on 8.4.1. Just in case anyone needs it.