-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
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
<Edit /> submit button is offering to submit while the form is still in pristine state and hasn't been edited #4733
Comments
Nice idea for an enhancement. Feel free to open a PR to implement it. |
The render method of I am currently reading the import React, { FC, ReactElement, SyntheticEvent, ReactNode } from 'react';
import PropTypes from 'prop-types';
import {
Button as MuiButton,
Tooltip,
IconButton,
useMediaQuery,
makeStyles,
PropTypes as MuiPropTypes,
} from '@material-ui/core';
import { ButtonProps as MuiButtonProps } from '@material-ui/core/Button';
import { Theme } from '@material-ui/core';
import classnames from 'classnames';
import { Record, RedirectionSideEffect, useTranslate } from 'ra-core';
/**
* A generic Button with side icon. Only the icon is displayed on small screens.
*
* The component translates the label. Pass the icon as child.
* The icon displays on the left side of the button by default. Set alignIcon prop to 'right' to inverse.
*
* @example
*
* <Button label="Edit" color="secondary" onClick={doEdit}>
* <ContentCreate />
* </Button>
*
*/
const Button: FC<ButtonProps> = props => {
const {
alignIcon = 'left',
children,
classes: classesOverride,
className,
color,
disabled,
label,
size,
...rest
} = props;
const translate = useTranslate();
const classes = useStyles(props);
const isXSmall = useMediaQuery((theme: Theme) =>
theme.breakpoints.down('xs')
);
- const restProps = sanitizeButtonRestProps(rest);
+ const { pristine, ...restProps } = sanitizeButtonRestProps(rest);
return isXSmall ? (
label && !disabled ? (
<Tooltip title={translate(label, { _: label })}>
<IconButton
aria-label={translate(label, { _: label })}
className={className}
color={color}
{...restProps}
>
{children}
</IconButton>
</Tooltip>
) : (
<IconButton
className={className}
color={color}
disabled={disabled}
{...restProps}
>
{children}
</IconButton>
)
) : (
<MuiButton
className={classnames(classes.button, className)}
color={color}
size={size}
aria-label={label ? translate(label, { _: label }) : undefined}
- disabled={disabled}
+ disabled={disabled || pristine}
{...restProps}
>
{alignIcon === 'left' &&
children &&
React.cloneElement(children, {
className: classes[`${size}Icon`],
})}
{label && (
<span
className={classnames({
[classes.label]: alignIcon === 'left',
[classes.labelRightIcon]: alignIcon !== 'left',
})}
>
{translate(label, { _: label })}
</span>
)}
{alignIcon === 'right' &&
children &&
React.cloneElement(children, {
className: classes[`${size}Icon`],
})}
</MuiButton>
);
};
const useStyles = makeStyles(
{
button: {
display: 'inline-flex',
alignItems: 'center',
},
label: {
paddingLeft: '0.5em',
},
labelRightIcon: {
paddingRight: '0.5em',
},
smallIcon: {
fontSize: 20,
},
mediumIcon: {
fontSize: 22,
},
largeIcon: {
fontSize: 24,
},
},
{ name: 'RaButton' }
);
interface Props {
alignIcon?: 'left' | 'right';
children?: ReactElement;
classes?: object;
className?: string;
color?: MuiPropTypes.Color;
component?: ReactNode;
to?: string | { pathname: string; search: string };
disabled?: boolean;
label?: string;
size?: 'small' | 'medium' | 'large';
icon?: ReactElement;
onClick?: (e: MouseEvent) => void;
redirect?: RedirectionSideEffect;
variant?: string;
// May be injected by Toolbar
basePath?: string;
handleSubmit?: (event?: SyntheticEvent<HTMLFormElement>) => Promise<Object>;
handleSubmitWithRedirect?: (redirect?: RedirectionSideEffect) => void;
invalid?: boolean;
onSave?: (values: object, redirect: RedirectionSideEffect) => void;
saving?: boolean;
submitOnEnter?: boolean;
pristine?: boolean;
record?: Record;
resource?: string;
undoable?: boolean;
}
export type ButtonProps = Props & MuiButtonProps;
export const sanitizeButtonRestProps = ({
// The next props are injected by Toolbar
basePath,
handleSubmit,
handleSubmitWithRedirect,
invalid,
onSave,
- pristine,
record,
redirect,
resource,
saving,
submitOnEnter,
undoable,
...rest
}: any) => rest;
Button.propTypes = {
alignIcon: PropTypes.oneOf(['left', 'right']),
children: PropTypes.element,
classes: PropTypes.object,
className: PropTypes.string,
color: PropTypes.oneOf(['default', 'inherit', 'primary', 'secondary']),
disabled: PropTypes.bool,
label: PropTypes.string,
size: PropTypes.oneOf(['small', 'medium', 'large']),
};
Button.defaultProps = {
color: 'primary',
size: 'small',
};
export default Button; Do you think that would be enough? I am unsure if I am also not seing the |
@kopax, I would take |
I have tried but the value is always |
I can't look into it right now. Sorry. |
No worries, I can't tell how the button is created within the form nor where is the form, I've checked |
Fixed by #4773 |
Yes, and I am grateful to @WiXSL and that you accepted with welcoming the feature. |
Minor versions are released monthly. See the Milestones page for a schedule of the release dates. |
Now that 3.6.0 is out, I am testing it in our back office app, and unfortunately, this is not working out of the box. The I have submitted #4904 that fixes it. |
What you were expecting:
I expect the submit button to be disabled if the form is still in
pristine
stateWhat happened instead:
The submit button is always enabled
Steps to reproduce:
https://marmelab.com/react-admin-demo/#/customers/129
Related code:
This is how a react-final-form submit button can solve the issue
Environment
The text was updated successfully, but these errors were encountered: