EasyCorp / EasyAdminBundle

EasyAdmin is a fast, beautiful and modern admin generator for Symfony applications.
MIT License
4.04k stars 1.02k forks source link

No way to disable fields based on entity property #6406

Open nicklocking opened 1 month ago

nicklocking commented 1 month ago

Describe the bug

Imagine you have an Order entity. It has a property named address (string) and submitted (bool). If the order is submitted=false, the address property can be edited. If the order is submitted=true, it cannot.

I can't work out a clean way of doing this with the existing EasyAdmin code. I can get to a point where I can optionally add fields to the edit form by hooking in to createEditFormBuilder, but they don't appear styled like EasyAdmin form fields so it feels like there must be a better way.

In the same way that Field::formatValue() takes a callable function, I would expect there to be some sort of Field::customizeField() method that takes a similar callable.

To Reproduce

Create entity as described above and then attempt to make a field's disabled property dynamic based on another entity property.

a-r-m-i-n commented 1 month ago

In edit mode you can access $this->adminContext and from it the entity dto and the actual instance. Then you can change the configuration to your needs, based on given values, in configureFields method of your CrudController.

zorn-v commented 1 month ago

https://github.com/EasyCorp/EasyAdminBundle/issues/6102 I have same problem and do it via security voter and setPermission on field. Will not work on index page, but I just disabled that field there.

Something like this in my case

//in controller configureFields
Field::new('disabled')->setPermission('NOT_YOURSELF')->setDisabled(Crud::PAGE_INDEX === $pageName)
<?php

namespace App\Security\Voter;

use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;

class NotYourselfVoter extends Voter
{
    public const ATTR = 'NOT_YOURSELF';

    public function __construct(
        private AdminContextProvider $adminProvider,
    ) {}

    protected function supports(string $attribute, mixed $subject): bool
    {
        return $attribute === self::ATTR;
    }

    protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
    {
        $user = $token->getUser();
        // if the user is anonymous, grant access
        if (!$user instanceof UserInterface) {
            return true;
        }

        if (null === $entity = $this->adminProvider->getContext()->getEntity()->getInstance()) {
            return true;
        }

        return $entity->getUserIdentifier() !== $user->getUserIdentifier();
    }
}
zorn-v commented 1 month ago

I have same problem

Not the same :smile: - you need just disable it. Then as @a-r-m-i-n said inject admin context and something like

->setDisabled($this->adminProvider->getContext()->getEntity()->getInstance()?->isSubmitted() ?? false)