#1608878: Add CTools dropbutton to core made me realize that the "drop button" (I didn't know it was called that) was actually a reusable component, and exists in ctools. That is cool.

What would be even nicer is if I could use it in a View. Admin views frequently have columns for "view", "edit", "delete", "flag", "add to nodequeue", etc. that take up a ton of visual space. Merging them into a single column is possible, but gets ugly fast since you have random strings separated by a / or something.

Ideally, it would be possible to take a series of such string fields and compress them into a single drop button column. Then we could build administrative views that offer all sorts of operations in a single space-saving column.

In IRC, Earl indicated that it "shouldn't be that hard to implement". Famous last words, I know. :-)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

Status: Active » Needs review
FileSize
4.03 KB
3.88 KB

Earl was right.

Attached a patch and a view to test this feature.

tim.plunkett’s picture

Status: Needs review » Needs work
+++ b/handlers/views_handler_field_ctools_dropdown.incundefined
@@ -0,0 +1,85 @@
+ * @todo
+ * Inherit from views_handler_field_contextual_links to save quite some code.

This looks promising :)

+++ b/handlers/views_handler_field_ctools_dropdown.incundefined
@@ -0,0 +1,85 @@
+      if (empty($this->view->field[$field]->last_render_text)) {
+        continue;
+      }
+      $title = $this->view->field[$field]->last_render_text;
+++ b/handlers/views_handler_field_ctools_dropdown.incundefined
@@ -0,0 +1,85 @@
+      if (!empty($title)) {

How are these different?

+++ b/handlers/views_handler_field_ctools_dropdown.incundefined
@@ -0,0 +1,85 @@
+          'href' => $path, 'title' => $title,

Might as well split this over two lines.

+++ b/handlers/views_handler_field_ctools_dropdown.incundefined
@@ -0,0 +1,85 @@
+      $ops = theme('links__ctools_dropbutton', array('links' => $links, 'attributes' => array('class' => array('links', 'inline'))));
+
+      return $ops;

$ops? Also, why not just return theme()?

bojanz’s picture

Oh, following (and will review later).
I currently create a new handler for each group of contextual links I need to show in a dropbutton (order, node, product), having a generic solution would be awesome.

dawehner’s picture

Assigned: Unassigned » dawehner

Assign to myself to work on that on the train.

dawehner’s picture

Status: Needs work » Needs review
FileSize
8.46 KB

So here is a total rework which uses the full power of inheritance etc.

Thanks for the review, you are right, i changed this points.

dawehner’s picture

FileSize
9.73 KB

The new view

Status: Needs review » Needs work

The last submitted patch, 1608920-dropdown-field-1608920.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
dawehner’s picture

This time a better working version, sorry removed something exactly before creating the patch.

damiankloip’s picture

Yes, that patch looks better. That seems to be working as expected now.

bojanz’s picture

$form['fields']['#destination'] = t('Fields to be included as ctools dropdown button.');

#destination should be #description.

I tried and couldn't get it to work.
I added "Commerce Product: Edit" and "Commerce Product: Delete" fields (both just output a link by returning l($text, $link)...)
I then added the dropbutton field (tried with contextual as well), and selected those two fields.
Got broken links that had the entire HTML as the label, generated like this:

<a href="/?destination=admin/commerce/products"><a href="/admin/commerce/products/12/delete?destination=admin/commerce/products">delete</a></a>

I probably missed something, but I expected that to work.
Furthermore, in Commerce and related modules, we have handlers that do something like this:

  function render($values) {
    $product_id = $this->get_value($values, 'product_id');

    // Get the operations links.
    $links = menu_contextual_links('commerce-product', 'admin/commerce/products', array($product_id));

    // Render as links
    return theme('links', array('links' => $links, 'attributes' => array('class' => array('links', 'inline', 'operations'))));
    // or perhaps as dropbuttons
    return array(
      '#markup' => theme('links__ctools_dropbutton', array('links' => $links, 'attributes' => array('class' => array('links', 'inline')))),
    );
  }

So my ideal handler would be entity-type-agnostic, and call menu_contextual_links() for me.
The url ('admin/commerce/product') could be taken from the field definition, or the handler could do something like this:

// We can get the entity through get_result_entities(), of course.
$uri = entity_uri($entity_type, $entity);
$links = menu_contextual_links(str_replace('-', '_', $entity_type), $uri['path'], array());

(Unsure if that's considered abuse of entity_uri(). Would work for products, orders, nodes... Not sure about other entity types).

That's my perspective (which doesn't need to affect the work here of course), with a touch of bikeshedding.

bojanz’s picture

Also note that regardless of the implementation, we need to add the dropbutton CSS when the field is used so that it actually looks the same as in Views admin.

Something like:

/**
 * Implement hook_views_pre_render().
 */
function views_views_pre_render(&$view) {
  static $done = FALSE;
  
  $has_field = FALSE;
  foreach ($views->field as $field) {
    if ($field instanceof views_handler_field_ctools_dropdown) {
      $has_field = TRUE;
    }
  }

  if ($has_field && !$done) {
    // Add the Views dropbutton CSS so that links provided by
    // views_handler_field_ctools_dropdown are styled properly.
    drupal_add_css(drupal_get_path('module', 'views') . '/css/views-admin.ctools.css');
    drupal_add_css(drupal_get_path('module', 'views') . '/css/views-admin.seven.css');

    $done = TRUE;
  }
}
dawehner’s picture

$form['fields']['#destination'] = t('Fields to be included as ctools dropdown button.');

Ups right... this happens if you use the autocompletion of your ide.

I added "Commerce Product: Edit" and "Commerce Product: Delete" fields (both just output a link by returning l($text, $link)...)

The current patch assumes that you create links in the way views create links which means that you set $this->options['alter']['path'].
Once you have that $this->get_links() can work as expected and return something like
array(array('href' => ...)). This structure is needed both by contextual links and ctools dropbutton. In theory though both ways should be supported. At least there should be a way to support multiple links from a single field.

What about adding a checkbox to add the js/css or not.

Regarding the idea of using menu_contextual_links i think once we support multiple links from a single field we could build an additional field handler for that. We can't support just links like that, because people will come up with crazy views-configured custom links.

dawehner’s picture

Ah maybe the css works for me already because i use the rubik admin theme, will check that later.

dawehner’s picture

ping

helior’s picture

Re-rolling; Fixed that typo mentioned in #11 and added an option to add css to match the style of drop-buttons in the views admin.

At least there should be a way to support multiple links from a single field.

Does someone have an example of a field that does this?

willieseabrook’s picture

#16 applies against 7.x-3.4 and is working great thanks guys.

Re the use case - I needed the functionality for a commerce site also - customer is unhappy with the clutter caused by various hyperlinks in the orders list.

I could also use this in a bunch of other places, so this is great functionality to add.

willieseabrook’s picture

Hmm, any reason why the options form doesn't inherit the parent?

I want to be able to give the table column a label!

  function options_form(&$form, &$form_state) {
    $all_fields = $this->view->display_handler->get_field_labels();

should be:

  function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);
    $all_fields = $this->view->display_handler->get_field_labels();
geek-merlin’s picture

* tested this patch
* added code from #18 which totally makes sense
* found a flaw: if a field is NOT linked it will instead be linked to frontpage. fixed that.

please test so we can get this in finally!

JvE’s picture

I'm loving it.

JvE’s picture

+++ b/handlers/views_handler_field_links.inc
@@ -0,0 +1,77 @@
+      if (!empty($this->options['destination'])) {
+        $links[$field]['query'] = drupal_get_destination();

External links should probably not get a destination query.

-      if (!empty($this->options['destination'])) {
+      if (!empty($this->options['destination']) && empty($this->view->field[$field]->options['alter']['external'])) {
        $links[$field]['query'] = drupal_get_destination();
geek-merlin’s picture

gee, yes!
(will test as i find time...)

solotandem’s picture

I was glad to find this issue with a solid patch.

My use case requires more of the URL options, like query arguments and alt titles, that are exposed on a views field. So, to utilize those options, the attached patch copies code from views_handler_field::render_as_link().

Anybody’s picture

Whao the patch works great and this is really an important feature!!

Do you think it makes sense to put this into views or should we better create a separate module (first) because it may need a lot of time to get this into views? Or has someone already done this via a module // or is it impossible?

Thanks a lot for your great work guys!

Anybody’s picture

I've just written a contrib sandbox module based on the patch which makes it possible to test and use the functionality while the patch is not part of views. I think some people will be happy about it. Furthermore I used the same names as in the patch so when the day comes where the patch makes it into the views release you should just be able to remove the module and everything should work fine.

If anyone of you would like to have maintainer access, please contact me. I'd be happy :)
Thanks a lot for your great work!

Sandbox: https://www.drupal.org/sandbox/anybody/views_ctools_dropdown

rudiedirkx’s picture

Status: Needs review » Needs work
FileSize
23.75 KB

Patch works great, but:

  • It would be nice to have the field check for menu item access, so different roles can use the same drop-button.
  • I think $form['fields'] in views_handler_field_links::options_form() should be #required.
  • Might be ctools' fault, but the dropdown looks like this, even with Views CSS included: view-drop-button-1608920 It's not absolute, like Views' buttons.
rudiedirkx’s picture

Status: Needs work » Needs review
FileSize
11.56 KB
2.58 KB

Fixed 2/3 issues:

  • check menu item access
  • Fields element #required
  • (And added function comments)

Patch & interdiff attached.

Did not fix:

  • broken style?, because I'm not sure it's my theme or CTools etc
rudiedirkx’s picture

Also added options_submit() to clean up unselected options from form state, because we don't want unselected options to be exported etc.

joelpittet’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community
FileSize
43.99 KB

This is awesome. The absolute positioning would be great but this definitely is a nice improvement, but I'd suggest a follow-up.

colan’s picture

We've recently switched our testing from the old qa.drupal.org to DrupalCI. Because of a bug in the new system, #2623840: Views (D7) patches not being tested, older patches must be re-uploaded. On re-uploading the patch, please set the status to "Needs Review" so that the test bot will add it to its queue.

If all tests pass, change the Status back to "Reviewed & tested by the community". We'll most likely commit the patch immediately without having to go through another round of peer review.

We apologize for the trouble, and appreciate your patience.

Anybody’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
11.83 KB

Re-uploaded #28 as of #30.

Anybody’s picture

Status: Needs review » Reviewed & tested by the community

  • colan committed aa989c4 on authored by dawehner
    Issue #1608920 by dawehner, rudiedirkx, axel.rutz, solotandem, Anybody,...
colan’s picture

Project: Views (for Drupal 7) » Drupal core
Version: 7.x-3.x-dev » 8.1.x-dev
Component: Code » views.module
Status: Reviewed & tested by the community » Patch (to be ported)

Thanks!

tstoeckler’s picture

Project: Drupal core » Views (for Drupal 7)
Version: 8.1.x-dev » 7.x-3.x-dev
Component: views.module » Code
Status: Patch (to be ported) » Fixed

In D8 this already exists since #1826604: Add a dropbutton field handler to Views. Feel free to re-open if I'm missing anything.

Status: Fixed » Closed (fixed)

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