Unique Field AJAX

A lightweight module that enforces unique values for specified fields with optional AJAX-based real-time validation.

unique_field_ajax
1,262 sites
38
drupal.org

Install

Drupal 11, 10, 9, 8 v2.2.3
composer require 'drupal/unique_field_ajax:^2.2'

Overview

The Unique Field AJAX module allows administrators to require that content supplied for specified fields is unique within the same content bundle. This is particularly useful for fields like product codes, serial numbers, email addresses, or any field where duplicate values should be prevented.

The module provides flexible uniqueness checking with options for per-language uniqueness, case-sensitive or case-insensitive matching, and AJAX-based real-time validation feedback. Administrators can customize error and warning messages using tokens to display links to existing content with duplicate values.

Beyond standard fields, the module also supports enforcing unique titles for content types through the content type configuration form. All configuration is done through the existing field settings interface, requiring no additional admin pages.

Features

  • Enforce unique values for single-value fields within the same content bundle
  • Per-language uniqueness checking - allows same value in different language versions while preventing duplicates within the same language
  • AJAX-based real-time validation that checks uniqueness as users type, showing immediate feedback before form submission
  • Case-sensitive or case-insensitive matching options for text-based fields
  • Optional 'Don't enforce uniqueness' mode that displays warnings but still allows saving duplicate values
  • Customizable error and warning messages with token support: %link (displays link to existing entity) and %label (displays field label)
  • Unique title enforcement for content types through the content type configuration form
  • Support for multiple field types: string, string_long, list_string, text, email, entity_reference, path, uri, link, integer, decimal, and color_field_type
  • Extensible through hooks allowing developers to modify uniqueness queries and results
  • No additional database tables or configuration entities required - uses Drupal's third-party settings system

Use Cases

Unique Product SKUs

An e-commerce site needs to ensure that each product has a unique SKU (Stock Keeping Unit). Configure the SKU field with unique enabled to prevent duplicate entries. Use case-sensitive matching if SKUs like 'ABC-123' and 'abc-123' should be treated as different products, or case-insensitive if they should be considered duplicates.

Unique Email Addresses for User Profiles

A membership site stores additional email addresses in a custom field on user profiles. Enable uniqueness on this email field to ensure no two members share the same contact email. The custom error message can be set to 'This email address is already associated with another account.'

Unique Article Titles per Language

A multilingual news site wants to prevent duplicate article titles within the same language while allowing the same title to be used in different translations. Enable the 'Per Language' option to allow 'Breaking News' in both English and Spanish versions while preventing two English articles with the same title.

Soft Enforcement with Warning Messages

A content management workflow where editors should be warned about potential duplicate content but still have the ability to save if necessary. Enable 'Don't enforce uniqueness' along with AJAX validation. Editors see a warning like 'Similar content already exists: %link' but can still save the content if they determine it's not actually a duplicate.

Serial Numbers with Real-time Validation

A manufacturing application tracks products by serial number. Enable AJAX validation so warehouse workers immediately see if a serial number already exists in the system as they type, before submitting the form. This prevents data entry errors and speeds up the registration process.

Unique External Reference IDs

An integration scenario where content is synced from an external system using unique identifiers. Configure a text field to store the external ID and enable uniqueness to prevent accidental import of duplicate records. Use the hook_query_unique_field_ajax_alter to add additional conditions like only checking against published content.

Tips

  • Use AJAX validation for the best user experience - users receive immediate feedback without waiting for form submission.
  • The %link token in custom messages creates a link to the existing content with the duplicate value, helping users identify and review the existing content.
  • Per-language uniqueness is particularly useful for multilingual sites where translated content may legitimately share field values like product names.
  • The 'Don't enforce uniqueness' option combined with custom warning messages is ideal for soft validation scenarios where users should be informed but not blocked.
  • Use hook_query_unique_field_ajax_alter to add custom conditions such as only checking published content or content within specific date ranges.
  • Export your field configuration to keep uniqueness settings in version control - settings are stored as third-party settings in the field configuration.
  • For programmatic entity creation, the uniqueness validation still applies during entity validation - use \$entity->validate() to check before saving.

Technical Details

Admin Pages 2
Content Type Edit Form - Unique Title Settings /admin/structure/types/manage/{node_type}

Configure unique title enforcement for a content type. When enabled, node titles must be unique within this content type. This section appears in the vertical tabs of the content type edit form.

Field Configuration - Unique Field Settings /admin/structure/types/manage/{node_type}/fields/{field_name}

Configure unique value enforcement for a specific field. This section appears in the vertical tabs of the field configuration form. Only available for single-value fields of supported types.

Hooks 2
hook_query_unique_field_ajax_alter

Allows modules to modify the database query used to check if a field value is unique. This hook can be used to add additional conditions, modify existing conditions, or completely change the uniqueness logic.

hook_unique_field_ajax_unique_results_alter

Allows modules to modify the results of the uniqueness check after the query has been executed. This can be used to override the uniqueness result based on custom logic.

Troubleshooting 6
Uniqueness check is not working for multi-value fields

The module only supports single-value fields. Multi-value (cardinality > 1) fields cannot be configured for uniqueness. Change the field's cardinality to 1 in the field storage settings if uniqueness is required.

AJAX validation shows error but form still submits

If 'Don't enforce uniqueness' is enabled, the AJAX validation will show warnings instead of errors, and the form will still be allowed to submit. Disable this option if you want to completely prevent duplicate submissions.

Unique field settings don't appear for my field type

The module only supports specific field types: string, string_long, list_string, text, email, entity_reference, path, uri, link, integer, decimal, and color_field_type. Other field types are not supported.

Case-insensitive matching not working as expected

By default, the module uses case-insensitive matching. If you see case-sensitive behavior, check if 'Case Sensitive' is enabled in the field settings. Also note that MySQL's default collation may affect case sensitivity - ensure your database collation matches your expectations.

Uniqueness is checked globally instead of per content type

The module enforces uniqueness within the same bundle (content type). If you're seeing cross-bundle validation, ensure you're testing within the same content type. The module adds a bundle condition to the query automatically.

Error message doesn't show the link to existing content

The %link token only works if the current user has view access to the existing entity with the duplicate value. If the user doesn't have access, 'Unknown entity' will be displayed instead.