Skip to content

Conversation

@martinjagodic
Copy link
Member

Addresses #565

Replaces #3891

This is a bit simpler than the first PR - there is only one condition possible instead of multiple conditions.

Usage:

name: conditional_string
widget: string
condition: 
  field: select # string
  value: a # string | boolean | number;
  operator: "!=" # | '=='  | '>' | '<' | '>=' | '<=';

Test plan:

test contidional widgets are added to dev-text config. Checkout this PR and npm run develop - see Conditional string field.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements conditional field visibility for the Decap CMS, allowing fields to be shown or hidden based on the values of other fields in the same collection. This addresses issue #565 and replaces PR #3891 with a simpler implementation supporting a single condition per field.

Key Changes:

  • Added Condition interface to TypeScript definitions allowing field conditions with operators (==, !=, >, <, >=, <=)
  • Implemented calculateCondition function to evaluate field visibility based on conditional logic
  • Integrated condition checks into field rendering and validation workflows

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/decap-cms-core/src/types/redux.ts Adds TypeScript Condition interface and condition property to CmsFieldBase
packages/decap-cms-core/index.d.ts Mirrors TypeScript definitions for external module consumers
packages/decap-cms-core/src/constants/configSchema.js Adds JSON schema validation for the condition field configuration
packages/decap-cms-core/src/components/Editor/EditorControlPane/EditorControlPane.js Implements conditional field logic in calculateCondition function and integrates it into validation and rendering
dev-test/config.yml Adds test examples for conditional string and object fields
Comments suppressed due to low confidence (1)

packages/decap-cms-core/src/components/Editor/EditorControlPane/EditorControlPane.js:98

  • Avoid automated semicolon insertion (93% of all statements in the enclosing function have an explicit semicolon).
  const condition = field.get('condition')

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 155 to 179
this.props.fields.forEach(field => {
if (field.get('widget') === 'hidden') return;
if (isFieldTranslatable(field, targetLocale, sourceLocale)) {
const copyValue = getFieldValue({
field,
entry,
locale: sourceLocale,
isTranslatable: sourceLocale !== defaultLocale,
});
if (copyValue) this.props.onChange(field, copyValue, undefined, i18n);
}
});
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copyFromOtherLocale function doesn't check if fields meet their condition before copying values. This could result in copying values to fields that are currently hidden due to unmet conditions. Consider adding a condition check similar to the one in the validate method and the render logic.

Copilot uses AI. Check for mistakes.
type: 'object',
properties: {
field: { type: 'string' },
value: { types: ['string', 'boolean'] },
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema uses types (plural) instead of type (singular) for the value property. This should be type: ['string', 'boolean', 'number'] to match JSON Schema standards and be consistent with how other properties are defined in the schema.

Suggested change
value: { types: ['string', 'boolean'] },
value: { type: ['string', 'boolean'] },

Copilot uses AI. Check for mistakes.
type: 'object',
properties: {
field: { type: 'string' },
value: { types: ['string', 'boolean'] },
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema definition for the value property is missing the number type. According to the TypeScript definition in redux.ts and index.d.ts, the value should accept string | boolean | number. Add 'number' to the types array: type: ['string', 'boolean', 'number'].

Suggested change
value: { types: ['string', 'boolean'] },
value: { type: ['string', 'boolean', 'number'] },

Copilot uses AI. Check for mistakes.
const operator = condition.get('operator') || '==';
const condValue = condition.get('value');

const condField = fields.find(f => f.get('name') === condFieldName);
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calculateCondition function doesn't handle the case where the referenced field is not found. If condField is undefined (when no field matches condFieldName), calling getFieldValue will fail. Add a null check:

const condField = fields.find(f => f.get('name') === condFieldName);
if (!condField) return false; // or true, depending on desired behavior
Suggested change
const condField = fields.find(f => f.get('name') === condFieldName);
const condField = fields.find(f => f.get('name') === condFieldName);
if (!condField) return false;

Copilot uses AI. Check for mistakes.
Comment on lines 110 to 113
case '==':
return condFieldValue == condValue;
case '!=':
return condFieldValue != condValue;
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comparison operators use loose equality (== and !=) instead of strict equality (=== and !==). This can lead to unexpected type coercion. For example, "0" == 0 would be true with loose equality. Consider using strict equality operators for more predictable behavior.

Copilot uses AI. Check for mistakes.
}

function calculateCondition({field, fields, entry, locale, isTranslatable}) {
const condition = field.get('condition')
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Missing semicolon at the end of the statement. This is inconsistent with the code style used elsewhere in the function (lines 101-103).

Suggested change
const condition = field.get('condition')
const condition = field.get('condition');

Copilot uses AI. Check for mistakes.
locale,
isTranslatable,
});
if (!isConditionMet) return
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing return value. When the condition is not met, this function returns undefined implicitly. For clarity and consistency with React rendering, explicitly return null:

if (!isConditionMet) return null;
Suggested change
if (!isConditionMet) return
if (!isConditionMet) return null;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant