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.
Comment | File | Size | Author |
---|---|---|---|
#40 | 2767857-list-builder-destination-40.patch | 18.06 KB | oxrc |
#32 | 2767857-list-builder-destination-32-interdiff.txt | 2.29 KB | Berdir |
#32 | 2767857-list-builder-destination-32.patch | 18.04 KB | Berdir |
#26 | 2767857-list-builder-destination-26-interdiff.txt | 4.36 KB | Berdir |
#26 | 2767857-list-builder-destination-26.patch | 19.42 KB | Berdir |
Comments
Comment #2
tstoecklerHere 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.Comment #4
tstoecklerI 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 toUpdatePathWithBrokenRoutingFilledTest
andDefaultViewsTest
are test only, so so far so good. I haven't figured out those two yet.Comment #5
tstoecklerAhh 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....
Comment #7
tstoecklerDue 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.
Comment #8
tstoecklerComment #9
BerdirSomewhat related: #2838968: BlockContentListBuilder should use RedirectDestinationTrait instead of hardcoding the collection link template
Comment #10
BerdirAs 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.
Comment #11
BerdirThis is what I had in mind.
Comment #13
tstoecklerI like that approach a lot, I it makes sense. I have only one super, super minor thing:
Super nitpick, but the cast is only relevant if the option is not there, right? If so, I would find
?: []
a bit clearer.Comment #14
tstoecklerComment #15
BerdirHa, 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.
Comment #16
tstoecklerOn
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?
Comment #17
BerdirThat'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...
Comment #19
dagmarSomewhat related #2668794: RedirectDestination:get doesn't use proper query parameters the same issue with the
destination
parameter exists for admin listings.Comment #20
dagmarSomewhat related #2668794: RedirectDestination:get doesn't use proper query parameters the same issue with the
destination
parameter exists for admin listings.Comment #21
dawehnerYeah these are the "small" things which sum up as being annoying. Having them fixed is just great.
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.
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.
Comment #22
BerdirNot 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 :)
Comment #24
BerdirReroll for now.
Comment #26
BerdirThe 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.
Comment #27
dawehnerThis is some nice improvement
Comment #28
BerdirYeah, 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.
Comment #30
Wim LeersLGTM!
Nit: "The updated URL object."
Comment #31
larowlanNo longer applies
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
Comment #32
BerdirRerolled and restored the constructor argument in NodeListBuilder, fine with keeping that.
Comment #33
Wim LeersComment #34
larowlanNot longer needed => No longer needed, can be fixed on commit
Comment #35
larowlanCan we get a change record here - thanks - there would be lots of contrib modules that can benefit from this
Comment #36
BerdirThis enough: https://www.drupal.org/node/2904582?
Comment #37
larowlanManually tested, works like it says on the box.
Committed as 401bd66 and pushed to 8.5.x. Thanks! >
Published change record.
Comment #40
oxrc CreditAttribution: oxrc as a volunteer commentedRe-rolled the patch from #32 to apply on 8.4.1. Just in case anyone needs it.