Skip to content

No Way to Set "isRequired" to True in Filter Params #595

Description

@grichards

API Platform version(s) affected: 4.0.3

Description
If you introspect the API Platform data and look at the Filter Params, there is a property "isRequired". It is always false no matter what I do with the API Platform configuration.

The FilterGuesser seems to want to evaluate that property to determine whether a filter should be "alwaysOn"... but I can't find any way tot set it.

How to reproduce

Create a Doctrine Entity with a SearchFilter configured.

In RA, introspect the API with something like this:

export function ETLogIntrospectedApiData() {
  const dataProvider = useDataProvider();
  const resourceName = useResourceContext();
  const schemaAnalyzer = hydraSchemaAnalyzer();

  dataProvider.introspect().then(({ data }: { data: Api }) => {
    console.log("API Data:", data);
    if (data && data.resources) {
      const resource = data.resources.find((res) => res.name === resourceName);
      if (resource) {
        schemaAnalyzer
          .getFiltersParametersFromSchema(resource)
          .then((params) => {
            console.log("Filter Params:", params);
          });
        schemaAnalyzer.getOrderParametersFromSchema(resource).then((params) => {
          console.log("Order Params:", params);
        });
      }
    }
  });
}

Notice in the console the Filter Params have an isRequired property set to false.

There are no docs about how to set it to true and various things I've tried with ApiProperty aren't working.

Activity

  1. slax57 commented on Mar 3, 2025

    @slax57
    Contributor

    After some digging, I managed to figure out that this isRequired property actually comes from the filter traits.

    Example for the SearchFilter, using the SearchFilterTrait, it is defined here:

    https://github.com/api-platform/core/blob/3f48c6fdd865e58d79fcdb7ac00e0be86718b3c8/src/Doctrine/Common/Filter/SearchFilterTrait.php#L77

    Unfortunately, for all currently implemented filter traits, this property is always set to false.
    So I guess this is not implemented yet.

    However, if you implement your own filter + trait, then it works fine!

    // SearchFilterTrait.php
    
    namespace App\Filter;
    
    // use ...
    
    trait SearchFilterTrait
    {
        // ...
        public function getDescription(string $resourceClass): array
        {
          // ...
                    foreach ($filterParameterNames as $filterParameterName) {
                        $description[$filterParameterName] = [
                            'property' => $propertyName,
                            'type' => $typeOfField,
                            'required' => true,
                            'strategy' => $strategy,
                            'is_collection' => str_ends_with((string) $filterParameterName, '[]'),
                        ];
                    }
            // ...
        }
        // ...
    }
    // SearchFilter.php
    
    namespace App\Filter;
    
    use App\Filter\SearchFilterTrait;
    // other imports...
    
    final class SearchFilter extends AbstractFilter implements SearchFilterInterface
    {
        use SearchFilterTrait;
    
        // ...
    }
    // Greeting.php
    
    namespace App\Entity;
    
    use App\Filter\SearchFilter;
    // other imports...
    
    #[ApiResource(mercure: true)]
    #[ORM\Entity]
    #[ApiFilter(OrderFilter::class, properties: ['name'], arguments: ['orderParameterName' => 'order'])]
    class Greeting
    {
        /**
         * The entity ID
         */
        #[ORM\Id]
        #[ORM\Column(type: 'integer')]
        #[ORM\GeneratedValue(strategy: 'SEQUENCE')]
        #[ORM\SequenceGenerator(sequenceName: 'greeting_seq', initialValue: 1, allocationSize: 100)]
        private ?int $id = null;
    
        /**
         * A nice person
         */
        #[ORM\Column]
        #[Assert\NotBlank]
        #[ApiFilter(SearchFilter::class, strategy: 'partial')]
        public string $name = '';
    }

    Image

  2. slax57 commented on Mar 3, 2025

    @slax57
    Contributor

    Thinking about it, I'm starting to question the rationale of assuming that having a required filter necessarily means it should be always displayed (alwaysOn).

    FTR: this rationale is implemented here:

    alwaysOn={filter.isRequired}

    To me, these are two different things.

    Wanting a filter to be always displayed or not is a UI concern, not a schema one. So in such a case, you would need to manually add the filter to your <Admin>, and set the alwaysOn prop there.
    In the end, to me, this is not necessarily a feature that would need to be implemented, but rather something to document.

  3. grichards commented on Mar 3, 2025

    @grichards
    Author

    Hello @slax57 , thanks for looking into this and for the suggesting about the custom trait!

    I think we have two issues:

    1. On the API Platform side, that "required" boolean should be configurable (if it's going to exist)... that seems indisputable to me.

    2. On the API Platform Admin side, I agree that how to interpret that value is more disputable.

    Personally, I encountered this issue because I was specifically looking for a quick / central way to control which filter inputs are visible by default and which are hidden behind the Add Filter menu.

    So for me, it would be convenient if the "required" boolean were configurable, and I'm satisfied with the API Platform Admin interpretation of that value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions