Problem/Motivation

Especially when the cardinality is 1, it is not natural for people to know they have to add another item before the existing one can be removed. The Remove option should always be there; regular validation can handle the enforcement of the field not being empty, same as when it is new and has no references yet.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Comments

mlncn created an issue. See original summary.

mlncn’s picture

OK this is actually a bug, that it does not already work the way i expect:

    if (!$allow_new && $allow_existing) {
      // Only count referencable entities if existing entities are allowed
      // to be referenced otherwise we set the variable to false.
      /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
      $handler = $this->selectionManager->getInstance($options);
      $have_multiple_existing_entities = count($handler->getReferenceableEntities(NULL, 'CONTAINS', 2)) > 1;
    } else {
      $have_multiple_existing_entities = FALSE;
    }
        // Determine if a reference may be removed.
        // Unless the user has permission to delete the entity, then they should
        // not be able to remove it if that will lead to its deletion.
        $may_remove_existing = $settings['removed_reference'] !== self::REMOVED_DELETE || $entity->access('delete');

        // Don't allow a user to remove the only entity if an entity is required
        // and the user cannot replace the entity if they remove it, because
        // this would put the form in an unrecoverable state.
        $can_replace_last_reference = $allow_new || ($allow_existing && $have_multiple_existing_entities);
        $reference_is_not_required = !$element['#required'] || $entities_count > 1 || $can_replace_last_reference;

        // Unsaved entities may always be removed.
        $may_remove = empty($entity_id) || ($may_remove_existing && $reference_is_not_required);

The reason the count seems to be off, at least in my case, is because getReferenceableEntities() returns an array of bundles, and inside that the entities, so in the case of the user reference it counts the one bundle— not the two entities that it should count. (There are many more than two, but the code limits the maximum results to two, because it only cares if it is zero, one, or more than one.)

This is indeed exactly what the getReferenceableEntities method says it will return:

   *   A nested array of entities, the first level is keyed by the
   *   entity bundle, which contains an array of entity labels (escaped),
   *   keyed by the entity ID.

We can probably save ourselves a step, and fix this bug, by using the countReferenceableEntities() method.

  • mlncn committed 01cb7751 on 1.0.x
    Issue #3504707: Allow removing the last item even for required fields
    
mlncn’s picture

Status: Active » Needs review

@TODO offer same patch to IEF