wieni / wmbert

A more user-friendly entity reference list field widget for Drupal 8.
MIT License
2 stars 1 forks source link

Sorting and Filtering of referenced items #5

Closed RoNoLo closed 3 years ago

RoNoLo commented 3 years ago

Hi, first of all thanks for this great widget. I am a Drupal veteran, but some things are so deep down handled in D8 and later, that I have no idea where is the correct point of configuration. Therefore I write this feature request.

Summary

It would be nice if I could define callbacks for filtering and or sorting.

Basic example

I noticed that my taxonomy items are not sorted alphabetically in the list of items I can add to an entity (in wmbert pulldown widget). Therefore I need a way sort it.

The second example for the need for filtering is a bit more complex. Imagin having 30 users. I have an entity where I can assign a few of them (imagin like an epic in a tool like JIRA or github). This entity has sub-entities like sub-tasks. When adding user references to these tasks I only want to have a list of users who are assigned to the parent epic. Currently all users are displayed.

I tried to dig deep into the Drupal handling of things and found Selection Handlers per Entity (or so), but I found no suitable and easy to understand how to use them. It seemed that they are based on Entity type. Not sure. An callback function, which will sort and filter sounds so much simpler. Even as an Event it would be okay for me.

It would be nice to have that functionallity in wmbert.

DieterHolvoet commented 3 years ago

I noticed that my taxonomy items are not sorted alphabetically in the list of items I can add to an entity (in wmbert pulldown widget). Therefore I need a way sort it.

You can change the field that will be used for sorting in the field settings:

Screenshot 2021-06-14 at 16 01 40

RoNoLo commented 3 years ago

Thanks for your feedback. I'm not sure if that should be always possible. I created Drupal entities, who currently do not show up in the admin UI. I've set up wmbert in the baseFieldDefinitions. So no UI atm for me.

DieterHolvoet commented 3 years ago

You can do the same in code by changing the handler_settings. This is all core behaviour btw, nothing wmbert specific.

$fields['some_field'] = BaseFieldDefinition::create('entity_reference')
    ->setSettings([
        'target_type' => $targetType,
        'handler_settings' => [
            'target_bundles' => NULL,
            'sort' => [
                'field' => 'name',
                'direction' => 'ASC',
            ],
        ],
    ]);

About you second question: that sounds a bit more complicated. TL;DR: This seems like a quite niche functionality which isn't really suited for inclusion in wmbert, but a custom selection handler will take you far.

Since you want to filter the referenceable entities based on another form value, you'll probably need to pass that value to the entity reference selection endpoint using AJAX. Like you said, you'll also need a custom entity selection handler. Here's an example:

function your_module_entity_reference_selection_alter(array &$handlers): void
{
    $handlers['wmbert:node']['class'] = Drupal\your_module\Plugin\EntityReferenceSelection\NodeWmBertSelection::class;
}
<?php

namespace Drupal\your_module\Plugin\EntityReferenceSelection;

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\wmbert\Plugin\EntityReferenceSelection\WmBertSelection;

class NodeWmBertSelection extends WmBertSelection
{
    protected function buildEntityQuery($match = null, $match_operator = 'CONTAINS')
    {
        $query = parent::buildEntityQuery($match, $match_operator);

        // Work with the existing query by calling parent::buildEntityQuery
        // or create a brand new query and return that one.

        return $query;
    }
}

By doing this, you're only overriding the node selection handler. You can replace node in wmbert:node with a different entity type ID.

What you can also do is not override the default wmbert node selection handler, but create a new one and use it only for a specific field.

$fields['some_field'] = BaseFieldDefinition::create('entity_reference')
    ->setSettings([
        'handler' => 'some_custom_handler',
    ]);
<?php

namespace Drupal\your_module\Plugin\EntityReferenceSelection;

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\wmbert\Plugin\EntityReferenceSelection\WmBertSelection;

/**
 * @EntityReferenceSelection(
 *     id = "some_custom_handler",
 *     label = @Translation("Some custom selection"),
 *     group = "your_module",
 *     weight = 1,
 * )
 */
class SomeCustomSelection extends WmBertSelection
{
}
RoNoLo commented 3 years ago

Thank you very much for your kind help.

DieterHolvoet commented 3 years ago

You're welcome!