I've created a view that provides a listing of a particular media type on my site. I'd like to place an "Add new" link at the top of this view and have it visible only to users who can actually add new media of that type. Does anyone know a straightforward way of doing this?

What I've tried:

  • Adding a View header component of type "Text area": Nope, can't restrict visibility
  • Using the menu's Menu block and trying to insert that as a Views header component: Nope, can't restrict visibility
  • Using the menu's Menu block and adding it to the Block layout with a specific "Show on this page" set to just the Views page I had created. This worked, but with several of these links to create, I would be unacceptably cluttering up my Block layout with one-off menu blocks.
  • Creating a menu with one menu item and rendering it with the "Rendered entity: Custom menu item": Nope, can't restrict visibility AND it renders in a useless way (unformatted data)

I find it strange that you can't create a Views header/footer element and specify its visibility based on roles/permissions.

Any ideas/solutions that won't be duplicative or hard to maintain?

  • Is Bypass access checks is checked when using Menu Block in the view header? Also, did you try this Menu Block visibility when placed in a normal region? The link itself can be very specific e.g. /node/add/article – Ismail Cherri Sep 14 at 13:56
  • @IsmailCherri no, Bypass was not selected. You can't apply permissions to Menu Blocks anyway, except when you add them to the Blocks layout, and I don't want my menu links in the layout. – theta-fish Sep 14 at 17:17
  • @IsmailCherri I forgot to mention that another thing I tried was to create the menu block and then add it to the layout. The unacceptable drawback there was that I have several of these to do and my block layout would have become unacceptably cluttered with blocks, each targeting a single view page. I'll add this to the question. – theta-fish Sep 14 at 17:18

A quick views only way you could:

Create an attachment with your link in a custom text or however you'd like to do it. Set the access permission for that attachment to your role and attach it to your main page display

If the user doesn't have that role the attachment should be empty/show the no results content

  • If by "Create an attachment," you mean "Create an Attachment display within the view," wouldn't that result in the Custom Text field being shown multiple times (the same number of times as the number of media records that are found by the query)? Also, if the view had no results, I would still want the "Add new" link to show. It's even more important when there are no existing media of that type. – theta-fish Sep 14 at 14:42
  • You could just set the attachment pager to show 1 item instead of all/a pager. You could also add the same custom text to the no results for the attachment (Or page display) – Leigh Mason Sep 14 at 14:51
  • True, but that requires me to maintain the same content in two places within an already confusing set-up. This seems like quite a hack. – theta-fish Sep 14 at 15:22
  • Usually when you start thinking this is a pain/mess doing it in views then that's time to consider doing some/all of it as a custom piece of coding. Views can't always cater for all use cases. Sometimes trying to bend it to what you want ends up messy. So you could perhaps look at using a views preprocess to add your required content. Or even write the whole thing custom in a module. – Leigh Mason Sep 14 at 15:29
  • Normally, I'd agree with you, but this is such a basic need that I've had many times before that I'm really surprised it's not available as functionality somehow. It's a major shortcoming of D8 Views in my opinion. In fact, without a workaround, it makes it significantly less likely I would use Views at all. – theta-fish Sep 14 at 17:23
up vote 0 down vote accepted

In the end, I followed a modified version of the answer Leigh Mason suggested:

  1. Created a separate View (named "Add new links") that queries for Blocks (instead of content or media)
  2. Created an "Embed" display on that view
  3. Set its filter to query for Block ID 999999 (to ensure it never gets results)
  4. Set its "No results" text to be the "Add new" link I want to display on my main view.
  5. Set its access to the permission for "[media type]: Create new media"
  6. Added the special view as a "View area" Header element on my main view. (Note that selecting it was a bit cryptic, as I had to choose my embed display, which was in the pick-list as "Embed_1")

The advantages to this approach are:

  • I only have to maintain the link HTML in one place
  • I can reuse this same special view for creating all my "Add new" links by creating new Embed displays and modifying the "No results" text using an override for just that specific display. (I can even change the administrative name to help me figure out which displays contain which links)

The disadvantages to this approach are:

  • It's a godawful hack that the next developer will curse me for
  • It uses a strange quirk to ensure that no records get returned (the super-high Block ID in the filter)

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.