Skip to content

Commit

Permalink
👽 Fix Django 4.2 admin form field markup
Browse files Browse the repository at this point in the history
The fieldboxes/multiple fields on a row was broken since the Django
4.2 upgrade because the markup changed extensively.

The markup now again matches a vanilla Django admin. Fielboxes are
slightly different since they gain additional wrappers, and the layout
of the errors relative to the input/help text changes.
  • Loading branch information
sergei-maertens committed Dec 10, 2024
1 parent 5ca2b7d commit 796dcc8
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,24 @@ export const AddressNlEditor = ({
return (
<>
<FormRow>
<Field name="specificTargetPaths" disabled={!!mappedVariable.targetPath}>
<Checkbox
name="specificTargetPathsCheckbox"
label={
<FormattedMessage
defaultMessage="Map specific subfields"
description="'Map specific subfields' checkbox label"
/>
}
helpText={
<FormattedMessage
description="'Map specific subfields' checkbox help text"
defaultMessage="Whether to map the specific subfield of addressNl component"
/>
}
checked={specificTargetPaths}
onChange={onSpecificTargetPathsChange}
/>
</Field>
<Checkbox
name="specificTargetPathsCheckbox"
label={
<FormattedMessage
defaultMessage="Map specific subfields"
description="'Map specific subfields' checkbox label"
/>
}
helpText={
<FormattedMessage
description="'Map specific subfields' checkbox help text"
defaultMessage="Whether to map the specific subfield of addressNl component"
/>
}
checked={specificTargetPaths}
onChange={onSpecificTargetPathsChange}
disabled={!!mappedVariable.targetPath}
/>
</FormRow>
<FormRow>
<Field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const DocumentType = ({name, label, loading, options, isDisabled, helpText}) =>

return (
<FormRow>
<Field name={name} label={label} helpText={helpText} noManageChildProps>
<Field name={name} label={label} helpText={helpText} disabled={isDisabled} noManageChildProps>
<>
<ReactSelect
name={name}
Expand Down
66 changes: 37 additions & 29 deletions src/openforms/js/components/admin/forms/Field.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,40 +77,48 @@ const Field = ({
modifiedChildren = React.cloneElement(children, childProps);
}
const [hasErrors, formattedErrors] = normalizeErrors(errors, intl);
const className = classNames({

const fieldClassName = classNames('flex-container', {
fieldBox: fieldBox,
errors: hasErrors,
'field--disabled': disabled,
});
const wrapperClassName = classNames({'field--disabled': disabled});

const fieldInputMarkup = (
<div className={fieldClassName}>
{label && (
<label className={required ? 'required' : ''} htmlFor={htmlFor}>
{label}
</label>
)}
{modifiedChildren}
</div>
);

const errorsMarkup = hasErrors && (
<ErrorList classNamePrefix={errorClassPrefix} classNameModifier={errorClassModifier}>
{formattedErrors}
</ErrorList>
);

const helpMarkup = helpText && (
<div className="help" id={`id_${name}_helptext`}>
<div>{helpText}</div>
</div>
);

return (
return fieldBox ? (
<div className={wrapperClassName}>
{errorsMarkup}
{fieldInputMarkup}
{helpMarkup}
</div>
) : (
<>
{!fieldBox && hasErrors ? (
<ErrorList classNamePrefix={errorClassPrefix} classNameModifier={errorClassModifier}>
{formattedErrors}
</ErrorList>
) : null}
<div className={className}>
{fieldBox && hasErrors ? (
<ErrorList classNamePrefix={errorClassPrefix} classNameModifier={errorClassModifier}>
{formattedErrors}
</ErrorList>
) : null}

<div className="flex-container">
{label && (
<label className={required ? 'required' : ''} htmlFor={htmlFor}>
{label}
</label>
)}
{modifiedChildren}
</div>

{helpText ? (
<div className="help" id={`id_${name}_helptext`}>
<div>{helpText}</div>
</div>
) : null}
{errorsMarkup}
<div className={wrapperClassName}>
{fieldInputMarkup}
{helpMarkup}
</div>
</>
);
Expand Down
12 changes: 10 additions & 2 deletions src/openforms/js/components/admin/forms/FormRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ const FormRow = ({fields = [], children}) => {
let hasErrors = false;
const validationErrors = useContext(ValidationErrorContext);

let hasAnyFieldBox = false;
// process (validation) errors here
const processedChildren = React.Children.map(children, child => {
// check if it *looks* like a field
let {name, errors} = child.props;
let {name, errors, fieldBox = false} = child.props;
if (fieldBox) hasAnyFieldBox = true;

if (!name) return child;

const childErrors = validationErrors
Expand Down Expand Up @@ -45,7 +48,12 @@ const FormRow = ({fields = [], children}) => {
{errors: processedChildren.length === 1 && hasErrors},
...fieldClasses
);
return <div className={className}>{processedChildren}</div>;
const inner = hasAnyFieldBox ? (
<div className="flex-container form-multiline">{processedChildren}</div>
) : (
processedChildren
);
return <div className={className}>{inner}</div>;
};

FormRow.propTypes = {
Expand Down
18 changes: 8 additions & 10 deletions src/openforms/js/components/admin/forms/FormRow.stories.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import {AdminChangeFormDecorator} from 'components/admin/form_design/story-decorators';

import Field from './Field';
import Fieldset from './Fieldset';
import FormRow from './FormRow';
import {TextInput} from './Inputs';

const FormDecorator = Story => (
<form>
<Fieldset>
<Story />
</Fieldset>
</form>
);

export default {
title: 'Admin/Django/FormRow',
component: FormRow,
decorators: [FormDecorator],
decorators: [AdminChangeFormDecorator],
parameters: {
adminChangeForm: {
wrapFieldset: true,
},
},
};

export const SingleField = {
Expand Down
10 changes: 3 additions & 7 deletions src/openforms/js/components/admin/forms/Inputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,8 @@ const Checkbox = ({name, label, helpText, noVCheckbox = false, ...extraProps}) =
name = prefix ? `${prefix}-${name}` : name;
const idFor = disabled ? undefined : `id_${name}`;
return (
<>
<div
className={classNames('flex-container', 'checkbox-row', {
'checkbox-row--disabled': disabled,
})}
>
<div className={classNames({'field--disabled': disabled})}>
<div className="flex-container checkbox-row">
<input type="checkbox" name={name} id={idFor} {...extraProps} />{' '}
<label className={classNames('inline', {vCheckboxLabel: !noVCheckbox})} htmlFor={idFor}>
{label}
Expand All @@ -118,7 +114,7 @@ const Checkbox = ({name, label, helpText, noVCheckbox = false, ...extraProps}) =
<div>{helpText}</div>
</div>
)}
</>
</div>
);
};

Expand Down

0 comments on commit 796dcc8

Please sign in to comment.