Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relational custom validation based on the length doesn't work as expected #13354

Open
janwillemvd opened this issue May 17, 2022 · 9 comments
Open
Labels

Comments

@janwillemvd
Copy link

janwillemvd commented May 17, 2022

Describe the Bug

First of all: thanks for building Directus. We've been playing around with it a few days now and we love it!

However, we might have encountered a small bug. I'm trying to add some validation to a M2A field, but some things don't work as expected.

I've created three collections: article, page and banner. In the banner collection I created the M2A field 'link' which should be required and it should only link to a maximum of one other record. I don't want multiple articles and/or pages to be linked at the same time for one banner record. Therefore, I've added a validation rule to that M2A field:

Screenshot 2022-05-17 at 11 19 08

However, this validation rule doesn't work as expected:
Screenshot 2022-05-17 at 11 22 43

In the above screenshot I only linked one item (the article 'Foo') and this should be allowed according to the validation rule (length equals to 1).

When I link multiple items or nothing at all the validation is also triggered (which is expected).

To Reproduce

I've created a snapshot of the example data model so one can simply reproduce this.

Steps to reproduce:

  1. Create a page and an article a
  2. Create a banner and try to link only one page or only one article to the banner
  3. When you try to save the banner the error shows up
The YAML snapshot
version: 1
directus: 9.10.0
collections:
  - collection: article
    meta:
      collection: article
      icon: null
      note: null
      display_template: '{{name}}'
      hidden: false
      singleton: false
      translations: null
      archive_field: status
      archive_app_filter: true
      archive_value: archived
      unarchive_value: draft
      sort_field: sort
      accountability: all
      color: null
      item_duplication_fields: null
      sort: null
      group: null
      collapse: open
    schema:
      schema: public
      name: article
      comment: null
  - collection: banner
    meta:
      collection: banner
      icon: null
      note: null
      display_template: '{{link.collection}}'
      hidden: false
      singleton: false
      translations: null
      archive_field: status
      archive_app_filter: true
      archive_value: archived
      unarchive_value: draft
      sort_field: sort
      accountability: all
      color: null
      item_duplication_fields: null
      sort: null
      group: null
      collapse: open
    schema:
      schema: public
      name: banner
      comment: null
  - collection: banner_link
    meta:
      collection: banner_link
      icon: import_export
      note: null
      display_template: null
      hidden: true
      singleton: false
      translations: null
      archive_field: null
      archive_app_filter: true
      archive_value: null
      unarchive_value: null
      sort_field: null
      accountability: all
      color: null
      item_duplication_fields: null
      sort: null
      group: null
      collapse: open
    schema:
      schema: public
      name: banner_link
      comment: null
  - collection: page
    meta:
      collection: page
      icon: null
      note: null
      display_template: '{{name}}'
      hidden: false
      singleton: false
      translations: null
      archive_field: status
      archive_app_filter: true
      archive_value: archived
      unarchive_value: draft
      sort_field: sort
      accountability: all
      color: null
      item_duplication_fields: null
      sort: null
      group: null
      collapse: open
    schema:
      schema: public
      name: page
      comment: null
fields:
  - collection: article
    field: id
    type: uuid
    schema:
      name: id
      table: article
      schema: public
      data_type: uuid
      is_nullable: false
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: true
      is_primary_key: true
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: article
      field: id
      special:
        - uuid
      interface: input
      options: null
      display: null
      display_options: null
      readonly: true
      hidden: true
      sort: 1
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: status
    type: string
    schema:
      name: status
      table: article
      schema: public
      data_type: character varying
      is_nullable: false
      generation_expression: null
      default_value: draft
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: article
      field: status
      special: null
      interface: select-dropdown
      options:
        choices:
          - text: $t:published
            value: published
          - text: $t:draft
            value: draft
          - text: $t:archived
            value: archived
      display: labels
      display_options:
        showAsDot: true
        choices:
          - text: $t:published
            value: published
            foreground: '#FFFFFF'
            background: var(--primary)
          - text: $t:draft
            value: draft
            foreground: '#18222F'
            background: '#D3DAE4'
          - text: $t:archived
            value: archived
            foreground: '#FFFFFF'
            background: var(--warning)
      readonly: false
      hidden: false
      sort: 3
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: sort
    type: integer
    schema:
      name: sort
      table: article
      schema: public
      data_type: integer
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: 32
      numeric_scale: 0
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: article
      field: sort
      special: null
      interface: input
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: 4
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: user_created
    type: uuid
    schema:
      name: user_created
      table: article
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
    meta:
      collection: article
      field: user_created
      special:
        - user-created
      interface: select-dropdown-m2o
      options:
        template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
      display: user
      display_options: null
      readonly: true
      hidden: true
      sort: 5
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: date_created
    type: timestamp
    schema:
      name: date_created
      table: article
      schema: public
      data_type: timestamp with time zone
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: article
      field: date_created
      special:
        - date-created
      interface: datetime
      options: null
      display: datetime
      display_options:
        relative: true
      readonly: true
      hidden: true
      sort: 6
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: user_updated
    type: uuid
    schema:
      name: user_updated
      table: article
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
    meta:
      collection: article
      field: user_updated
      special:
        - user-updated
      interface: select-dropdown-m2o
      options:
        template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
      display: user
      display_options: null
      readonly: true
      hidden: true
      sort: 7
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: date_updated
    type: timestamp
    schema:
      name: date_updated
      table: article
      schema: public
      data_type: timestamp with time zone
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: article
      field: date_updated
      special:
        - date-updated
      interface: datetime
      options: null
      display: datetime
      display_options:
        relative: true
      readonly: true
      hidden: true
      sort: 8
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: article
    field: name
    type: string
    schema:
      name: name
      table: article
      schema: public
      data_type: character varying
      is_nullable: false
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: true
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: article
      field: name
      special: null
      interface: input
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: false
      sort: 2
      width: full
      translations: null
      note: null
      conditions: null
      required: true
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: id
    type: uuid
    schema:
      name: id
      table: banner
      schema: public
      data_type: uuid
      is_nullable: false
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: true
      is_primary_key: true
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner
      field: id
      special:
        - uuid
      interface: input
      options: null
      display: null
      display_options: null
      readonly: true
      hidden: true
      sort: 1
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: status
    type: string
    schema:
      name: status
      table: banner
      schema: public
      data_type: character varying
      is_nullable: false
      generation_expression: null
      default_value: draft
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner
      field: status
      special: null
      interface: select-dropdown
      options:
        choices:
          - text: $t:published
            value: published
          - text: $t:draft
            value: draft
          - text: $t:archived
            value: archived
      display: labels
      display_options:
        showAsDot: true
        choices:
          - text: $t:published
            value: published
            foreground: '#FFFFFF'
            background: var(--primary)
          - text: $t:draft
            value: draft
            foreground: '#18222F'
            background: '#D3DAE4'
          - text: $t:archived
            value: archived
            foreground: '#FFFFFF'
            background: var(--warning)
      readonly: false
      hidden: false
      sort: 3
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: sort
    type: integer
    schema:
      name: sort
      table: banner
      schema: public
      data_type: integer
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: 32
      numeric_scale: 0
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner
      field: sort
      special: null
      interface: input
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: 4
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: user_created
    type: uuid
    schema:
      name: user_created
      table: banner
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
    meta:
      collection: banner
      field: user_created
      special:
        - user-created
      interface: select-dropdown-m2o
      options:
        template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
      display: user
      display_options: null
      readonly: true
      hidden: true
      sort: 5
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: date_created
    type: timestamp
    schema:
      name: date_created
      table: banner
      schema: public
      data_type: timestamp with time zone
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner
      field: date_created
      special:
        - date-created
      interface: datetime
      options: null
      display: datetime
      display_options:
        relative: true
      readonly: true
      hidden: true
      sort: 6
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: user_updated
    type: uuid
    schema:
      name: user_updated
      table: banner
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
    meta:
      collection: banner
      field: user_updated
      special:
        - user-updated
      interface: select-dropdown-m2o
      options:
        template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
      display: user
      display_options: null
      readonly: true
      hidden: true
      sort: 7
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: date_updated
    type: timestamp
    schema:
      name: date_updated
      table: banner
      schema: public
      data_type: timestamp with time zone
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner
      field: date_updated
      special:
        - date-updated
      interface: datetime
      options: null
      display: datetime
      display_options:
        relative: true
      readonly: true
      hidden: true
      sort: 8
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: name
    type: string
    schema:
      name: name
      table: banner
      schema: public
      data_type: character varying
      is_nullable: false
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: true
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner
      field: name
      special: null
      interface: input
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: false
      sort: 2
      width: full
      translations: null
      note: null
      conditions: null
      required: true
      group: null
      validation: null
      validation_message: null
  - collection: banner_link
    field: id
    type: integer
    schema:
      name: id
      table: banner_link
      schema: public
      data_type: integer
      is_nullable: false
      generation_expression: null
      default_value: nextval('banner_link_id_seq'::regclass)
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: 32
      numeric_scale: 0
      is_unique: true
      is_primary_key: true
      has_auto_increment: true
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner_link
      field: id
      special: null
      interface: null
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: null
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner_link
    field: banner_id
    type: uuid
    schema:
      name: banner_id
      table: banner_link
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: banner
      foreign_key_column: id
    meta:
      collection: banner_link
      field: banner_id
      special: null
      interface: null
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: null
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner_link
    field: item
    type: string
    schema:
      name: item
      table: banner_link
      schema: public
      data_type: character varying
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner_link
      field: item
      special: null
      interface: null
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: null
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: banner_link
    field: collection
    type: string
    schema:
      name: collection
      table: banner_link
      schema: public
      data_type: character varying
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: banner_link
      field: collection
      special: null
      interface: null
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: null
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: id
    type: uuid
    schema:
      name: id
      table: page
      schema: public
      data_type: uuid
      is_nullable: false
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: true
      is_primary_key: true
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: page
      field: id
      special:
        - uuid
      interface: input
      options: null
      display: null
      display_options: null
      readonly: true
      hidden: true
      sort: 1
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: status
    type: string
    schema:
      name: status
      table: page
      schema: public
      data_type: character varying
      is_nullable: false
      generation_expression: null
      default_value: draft
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: page
      field: status
      special: null
      interface: select-dropdown
      options:
        choices:
          - text: $t:published
            value: published
          - text: $t:draft
            value: draft
          - text: $t:archived
            value: archived
      display: labels
      display_options:
        showAsDot: true
        choices:
          - text: $t:published
            value: published
            foreground: '#FFFFFF'
            background: var(--primary)
          - text: $t:draft
            value: draft
            foreground: '#18222F'
            background: '#D3DAE4'
          - text: $t:archived
            value: archived
            foreground: '#FFFFFF'
            background: var(--warning)
      readonly: false
      hidden: false
      sort: 3
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: sort
    type: integer
    schema:
      name: sort
      table: page
      schema: public
      data_type: integer
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: 32
      numeric_scale: 0
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: page
      field: sort
      special: null
      interface: input
      options: null
      display: null
      display_options: null
      readonly: false
      hidden: true
      sort: 4
      width: full
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: user_created
    type: uuid
    schema:
      name: user_created
      table: page
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
    meta:
      collection: page
      field: user_created
      special:
        - user-created
      interface: select-dropdown-m2o
      options:
        template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
      display: user
      display_options: null
      readonly: true
      hidden: true
      sort: 5
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: date_created
    type: timestamp
    schema:
      name: date_created
      table: page
      schema: public
      data_type: timestamp with time zone
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: page
      field: date_created
      special:
        - date-created
      interface: datetime
      options: null
      display: datetime
      display_options:
        relative: true
      readonly: true
      hidden: true
      sort: 6
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: user_updated
    type: uuid
    schema:
      name: user_updated
      table: page
      schema: public
      data_type: uuid
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
    meta:
      collection: page
      field: user_updated
      special:
        - user-updated
      interface: select-dropdown-m2o
      options:
        template: '{{avatar.$thumbnail}} {{first_name}} {{last_name}}'
      display: user
      display_options: null
      readonly: true
      hidden: true
      sort: 7
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: date_updated
    type: timestamp
    schema:
      name: date_updated
      table: page
      schema: public
      data_type: timestamp with time zone
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: null
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: false
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: page
      field: date_updated
      special:
        - date-updated
      interface: datetime
      options: null
      display: datetime
      display_options:
        relative: true
      readonly: true
      hidden: true
      sort: 8
      width: half
      translations: null
      note: null
      conditions: null
      required: false
      group: null
      validation: null
      validation_message: null
  - collection: page
    field: name
    type: string
    schema:
      name: name
      table: page
      schema: public
      data_type: character varying
      is_nullable: true
      generation_expression: null
      default_value: null
      is_generated: false
      max_length: 255
      comment: null
      numeric_precision: null
      numeric_scale: null
      is_unique: true
      is_primary_key: false
      has_auto_increment: false
      foreign_key_schema: null
      foreign_key_table: null
      foreign_key_column: null
    meta:
      collection: page
      field: name
      special: null
      interface: input
      options: null
      display: raw
      display_options: null
      readonly: false
      hidden: false
      sort: 2
      width: full
      translations: null
      note: null
      conditions: null
      required: true
      group: null
      validation: null
      validation_message: null
  - collection: banner
    field: link
    type: alias
    schema: null
    meta:
      collection: banner
      field: link
      special:
        - m2a
      interface: list-m2a
      options: null
      display: null
      display_options:
        template: null
      readonly: false
      hidden: false
      sort: 9
      width: full
      translations: null
      note: null
      conditions: null
      required: true
      group: null
      validation:
        _and:
          - count(link):
              _eq: '1'
      validation_message: Please don't link multiple items at the same time.
relations:
  - collection: banner
    field: user_created
    related_collection: directus_users
    schema:
      constraint_name: banner_user_created_foreign
      table: banner
      column: user_created
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: NO ACTION
    meta:
      many_collection: banner
      many_field: user_created
      one_collection: directus_users
      one_field: null
      one_collection_field: null
      one_allowed_collections: null
      junction_field: null
      sort_field: null
      one_deselect_action: nullify
  - collection: banner
    field: user_updated
    related_collection: directus_users
    schema:
      constraint_name: banner_user_updated_foreign
      table: banner
      column: user_updated
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: NO ACTION
    meta:
      many_collection: banner
      many_field: user_updated
      one_collection: directus_users
      one_field: null
      one_collection_field: null
      one_allowed_collections: null
      junction_field: null
      sort_field: null
      one_deselect_action: nullify
  - collection: article
    field: user_created
    related_collection: directus_users
    schema:
      constraint_name: article_user_created_foreign
      table: article
      column: user_created
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: NO ACTION
    meta:
      many_collection: article
      many_field: user_created
      one_collection: directus_users
      one_field: null
      one_collection_field: null
      one_allowed_collections: null
      junction_field: null
      sort_field: null
      one_deselect_action: nullify
  - collection: article
    field: user_updated
    related_collection: directus_users
    schema:
      constraint_name: article_user_updated_foreign
      table: article
      column: user_updated
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: NO ACTION
    meta:
      many_collection: article
      many_field: user_updated
      one_collection: directus_users
      one_field: null
      one_collection_field: null
      one_allowed_collections: null
      junction_field: null
      sort_field: null
      one_deselect_action: nullify
  - collection: page
    field: user_created
    related_collection: directus_users
    schema:
      constraint_name: page_user_created_foreign
      table: page
      column: user_created
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: NO ACTION
    meta:
      many_collection: page
      many_field: user_created
      one_collection: directus_users
      one_field: null
      one_collection_field: null
      one_allowed_collections: null
      junction_field: null
      sort_field: null
      one_deselect_action: nullify
  - collection: page
    field: user_updated
    related_collection: directus_users
    schema:
      constraint_name: page_user_updated_foreign
      table: page
      column: user_updated
      foreign_key_schema: public
      foreign_key_table: directus_users
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: NO ACTION
    meta:
      many_collection: page
      many_field: user_updated
      one_collection: directus_users
      one_field: null
      one_collection_field: null
      one_allowed_collections: null
      junction_field: null
      sort_field: null
      one_deselect_action: nullify
  - collection: banner_link
    field: banner_id
    related_collection: banner
    schema:
      constraint_name: banner_link_banner_id_foreign
      table: banner_link
      column: banner_id
      foreign_key_schema: public
      foreign_key_table: banner
      foreign_key_column: id
      on_update: NO ACTION
      on_delete: SET NULL
    meta:
      many_collection: banner_link
      many_field: banner_id
      one_collection: banner
      one_field: link
      one_collection_field: null
      one_allowed_collections: null
      junction_field: item
      sort_field: null
      one_deselect_action: nullify
  - collection: banner_link
    field: item
    related_collection: null
    schema: null
    meta:
      many_collection: banner_link
      many_field: item
      one_collection: null
      one_field: null
      one_collection_field: collection
      one_allowed_collections:
        - article
        - page
      junction_field: banner_id
      sort_field: null
      one_deselect_action: nullify

Errors Shown

N/A

What version of Directus are you using?

9.10.0

What version of Node.js are you using?

16.13.0

What database are you using?

Postgres 13

What browser are you using?

Chrome, Firefox, Safari

How are you deploying Directus?

Running locally

@rijkvanzanten
Copy link
Member

This is because the app is sending the "detailed" structure for updates (cc @Nitwel):

{
  create: [{ title: 'example' }],
  update: [],
  delete: []
}

the count() runs against that object, which then fails (as it's not an array of values). To fix this, the API will have to read through and calculate what the count would be after the operation is done in order to validate against the proper count number.

@rijkvanzanten
Copy link
Member

Oh and the same will apply for o2m/m2m interfaces as well, as the logic is shared between those

@rijkvanzanten rijkvanzanten changed the title M2A custom validation based on the length doesn't work as expected Relational custom validation based on the length doesn't work as expected May 24, 2022
@lyneal

This comment was marked as off-topic.

@rijkvanzanten

This comment was marked as resolved.

@rasco
Copy link
Sponsor

rasco commented Jul 26, 2022

is there any kind of workaround we might be able to use for now?

@rijkvanzanten
Copy link
Member

is there any kind of workaround we might be able to use for now?

No

@rijkvanzanten
Copy link
Member

Linear: ENG-255

@curtisburns
Copy link

Just thought I'd pitch in to describe how I've just run into this issue myself. I was initially looking for a workaround for the absence of a one-2-one relation, or even a relation to a single object, as I've created a few of these for the 'compulsory' pages of my site.

I'm exploring ways to enable user-created navigation, which when linking to internal pages, I would ensure content creators can link to existing pages/items. Tree-view would be ideal for this, except it only works for recursive relationships and so is only suitable for creating a nested same-type relationship, and not within a parent of a different type:

E.g.

Menu > Menu link > [Menu link] Child link

I also need to be able to link to multiple collections (for example, homepage, contact, articles, cookie policy), so O2M and M2M are off the table. This leaves me with M2A.

For this to work, I've had to uncheck 'Treat as single object' for all the collections I wish to include in the M2A field as it's not possible otherwise (possible feature request here 😁). Then as I only need to link to one page only, I figured I would be clever by adding validation to check if the count of 'Internal Link' (as I've named it) is less than or equal to one. Unfortunately, I get a Count (Internal Link): validationError.undefined error, so no luck there.

In the meantime, I've just had to settle for a note stating 'Maximum of one' under the M2A field despite you being able to add more. Then when it comes to constructing the nav in my front-end, I'll just grab the first item only from the array.

Am I going about this the right way? Or is there another approach to this? A hard limit, or even the option to hide the 'Add existing' button conditionally would be great here. Other than that, absolutely loving Directus so far. Really great work, guys!

@JustinKoenig123
Copy link

is there any kind of workaround we might be able to use for now?

if you haven't found a workaround yet, you can use flows to validate your m2m and m2a fields. Using scripts you have the possibility to intercept the payload with filter trigger and output errors in the ui.

have a look: #16802

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: 📋 Backlog
7 participants