react#FormEventHandler TypeScript Examples
The following examples show how to use
react#FormEventHandler.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AlertAcceptForm.tsx From backstage with Apache License 2.0 | 6 votes |
AlertAcceptForm = forwardRef<
HTMLFormElement,
AlertAcceptFormProps
>(({ onSubmit, disableSubmit }, ref) => {
const [checked, setChecked] = useState(false);
const onFormSubmit: FormEventHandler = e => {
e.preventDefault();
onSubmit(null);
};
const onChecked = (_: ChangeEvent<HTMLInputElement>, isChecked: boolean) => {
setChecked(isChecked);
disableSubmit(!isChecked);
};
return (
<form ref={ref} onSubmit={onFormSubmit}>
<FormControl component="fieldset" fullWidth>
<FormControlLabel
label="My team can commit to making this change soon, or has already."
value={checked}
control={
<Checkbox color="primary" checked={checked} onChange={onChecked} />
}
/>
</FormControl>
</form>
);
})
Example #2
Source File: Prompt.tsx From mysterium-vpn-desktop with MIT License | 6 votes |
Prompt: React.FC<PropsWithChildren<PromptProps>> = ({
visible,
title,
onSubmit,
onCancel,
submitText = "OK",
children,
}) => {
if (!visible) {
return <></>
}
const handleOnSubmit: FormEventHandler = (evt) => {
evt.preventDefault()
onSubmit?.()
}
const handleCancel = () => {
onCancel?.()
}
return (
<Background>
<Box>
<form onSubmit={handleOnSubmit}>
<PromptTitle>{title}</PromptTitle>
{children}
<PromptButtons>
<PromptButtonOK type="submit">{submitText}</PromptButtonOK>
<OutlineButton onClick={handleCancel} type="button">
Cancel
</OutlineButton>
</PromptButtons>
</form>
</Box>
</Background>
)
}
Example #3
Source File: CheckboxField.tsx From typescript-fun with MIT License | 6 votes |
CheckboxField: FC<{
field: Field<boolean, FormErrorID>;
label: string;
}> = ({ field, label, ...rest }) => {
const handleChange = useCallback<FormEventHandler<HTMLInputElement>>(
event => {
field.onChange(event.currentTarget.checked);
},
[field],
);
const handleKeyPress = useCallback<KeyboardEventHandler<HTMLInputElement>>(
event => {
if (event.key === 'Enter') field.submit();
},
[field],
);
return (
<FormControl {...rest}>
<Checkbox
isChecked={field.value}
onChange={handleChange}
onKeyPress={handleKeyPress}
ref={field.ref}
>
{label}
</Checkbox>
</FormControl>
);
}
Example #4
Source File: KubernetesMigrationDismissForm.tsx From backstage with Apache License 2.0 | 5 votes |
KubernetesMigrationDismissForm = forwardRef<
HTMLFormElement,
KubernetesMigrationDismissFormProps
>(({ onSubmit, disableSubmit, alert }, ref) => {
const [services, setServices] = useState<Entity[]>(alert.data.services);
const onFormSubmit: FormEventHandler = e => {
/* Remember to prevent default form behavior */
e.preventDefault();
onSubmit({ services: services });
};
const onCheckboxChange = (
e: ChangeEvent<HTMLInputElement>,
checked: boolean,
) => {
if (checked) {
const service = findAlways(
alert.data.services,
s => s.id === e.target.value,
);
setServices(prevServices => prevServices.concat(service));
} else {
setServices(prevServices =>
prevServices.filter(p => p.id !== e.target.value),
);
}
};
/* Submit button is disabled by default. Use props.disableSubmit to toggle disabled state. */
useEffect(() => {
if (services.length) {
disableSubmit(false);
} else {
disableSubmit(true);
}
}, [services, disableSubmit]);
return (
/* All custom forms must accept a ref and implement an onSubmit handler. */
<form ref={ref} onSubmit={onFormSubmit}>
<FormControl component="fieldset" fullWidth>
<Typography color="textPrimary">
<b>Or choose which services to dismiss this alert for.</b>
</Typography>
<FormGroup>
{alert.data.services.map((service, index) => (
<FormControlLabel
key={`example-option-${index}`}
label={service.id}
value={service.id}
control={
<Checkbox
color="primary"
checked={services.some(p => p.id === service.id)}
onChange={onCheckboxChange}
/>
}
/>
))}
</FormGroup>
</FormControl>
</form>
);
})
Example #5
Source File: AlertSnoozeForm.tsx From backstage with Apache License 2.0 | 5 votes |
AlertSnoozeForm = forwardRef<
HTMLFormElement,
AlertSnoozeFormProps
>(({ onSubmit, disableSubmit }, ref) => {
const classes = useStyles();
const [duration, setDuration] = useState<Maybe<Duration>>(Duration.P7D);
useEffect(() => disableSubmit(false), [disableSubmit]);
const onFormSubmit: FormEventHandler = e => {
e.preventDefault();
if (duration) {
const repeatInterval = 1;
const today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);
onSubmit({
intervals: intervalsOf(duration, today, repeatInterval),
});
}
};
const onSnoozeDurationChange = (
_: ChangeEvent<HTMLInputElement>,
value: string,
) => {
setDuration(value as Duration);
};
return (
<form ref={ref} onSubmit={onFormSubmit}>
<FormControl component="fieldset" fullWidth>
<Typography color="textPrimary">
<b>For how long?</b>
</Typography>
<Box mb={1}>
<RadioGroup
name="snooze-alert-options"
value={duration}
onChange={onSnoozeDurationChange}
>
{AlertSnoozeOptions.map(option => (
<FormControlLabel
key={`snooze-alert-option-${option.duration}`}
label={option.label}
value={option.duration}
control={<Radio className={classes.radio} />}
/>
))}
</RadioGroup>
</Box>
</FormControl>
</form>
);
})
Example #6
Source File: TextInputField.tsx From typescript-fun with MIT License | 5 votes |
TextInputField: FC<{
field: FieldMaybeOptional<string, FormErrorID>;
icon?: ReactNode;
label: string;
type: 'text' | 'email' | 'password' | 'tel';
}> = ({ field, icon, label, type, ...rest }) => {
const handleChange = useCallback<FormEventHandler<HTMLInputElement>>(
({ currentTarget: { value } }) => {
if (isOptionalField(field)) {
field.onChange(value.length === 0 ? O.none : O.some(value));
} else {
field.onChange(value);
}
},
[field],
);
const handleKeyPress = useCallback<KeyboardEventHandler<HTMLInputElement>>(
event => {
if (event.key === 'Enter') field.submit();
},
[field],
);
const value = isOptionalField(field)
? pipe(
field.value,
O.getOrElse(() => ''),
)
: field.value;
const input = (
<Input
id={field.key}
type={type}
value={value}
onChange={handleChange}
onKeyPress={handleKeyPress}
ref={field.ref}
/>
);
return (
<FormControl
isRequired={!isOptionalField(field)}
isInvalid={field.isInvalid}
{...rest}
>
<FormLabel htmlFor={field.key}>{label}</FormLabel>
{icon ? (
<InputGroup>
<InputLeftElement>{icon}</InputLeftElement>
{input}
</InputGroup>
) : (
input
)}
<FormErrorMessage error={field.firstError} />
</FormControl>
);
}
Example #7
Source File: General.tsx From one-platform with MIT License | 4 votes |
export default function General ( { app }: IGeneralSettings ) {
const { forceRefreshApp } = useContext( AppContext );
const [ isDeleteModalOpen, setDeleteModalOpen ] = useState( false );
const [ deleteAppConfirmation, setDeleteAppConformation ] = useState( '' );
const history = useHistory();
const location = useLocation();
const { control, handleSubmit, formState: { errors, isValid }, watch, reset } = useForm<IAppInput>( {
mode: 'onBlur',
resolver: yupResolver( formSchema ),
defaultValues: {
name: '',
description: ''
},
} );
const [ isSaving, setIsSaving ] = useState( false );
const editedName = watch( 'name' );
const editedDescription = watch( 'description' );
const isChanged = useMemo( () => {
return editedName !== app.name || editedDescription !== app.description;
}, [app, editedName, editedDescription] );
const handleReset = useCallback( () => {
reset( {
name: app.name,
description: app.description
} );
}, [ app, reset ] );
const handleSaveApp = useCallback(( data: any ) => {
setIsSaving( true );
updateAppService( app.id, data )
.then( updatedApp => {
forceRefreshApp( updatedApp );
window.OpNotification?.success( { subject: 'App Updated Successfully!' } );
setIsSaving( false );
} )
.catch( err => {
window.OpNotification?.danger( { subject: 'An error occurred when updating the App.', body: 'Please try again later.' } );
console.error( err );
setIsSaving( false );
} );
}, [ app.id, forceRefreshApp ] );
useEffect( () => {
handleReset();
}, [ app, handleReset ] );
useEffect( () => {
const searchParams = new URLSearchParams( location.search );
if ( searchParams.get( 'action' ) === 'delete' ) {
setDeleteModalOpen( true );
} else {
setDeleteModalOpen( false );
}
}, [ location ] );
const handleOwnershipTransferToggle = () => {
/* TODO: gqlQuery for toggling ownership transfer */
};
const handleDeleteApp: FormEventHandler = ( event ) => {
event.preventDefault();
deleteAppService( app.id )
.then( () => {
window.OpNotification?.success( { subject: 'App Deleted Successfully!' } );
history.push( '/' );
} )
.catch( err => {
window.OpNotification?.danger( { subject: 'An error occurred when deleting the App.', body: 'Please try again later.' } );
console.error( err );
} );
};
const handleModalClose = () => {
/* Remove the new=true from the url search params */
const searchParams = new URLSearchParams( location.search );
searchParams.delete( 'action' );
history.replace( { search: searchParams.toString() } );
setDeleteAppConformation( '' );
};
return (
<>
<Stack hasGutter>
<StackItem>
<Form onSubmit={ handleSubmit( handleSaveApp ) } onReset={ handleReset }>
<Card isRounded>
<CardBody>
<Grid hasGutter>
<GridItem>
<FormGroup
isRequired
fieldId="name"
label="App Name"
helperText="Name of the project"
helperTextInvalid={ errors.name?.message }
validated={errors.name ? 'error' : 'default' }>
<Controller
name="name"
control={ control }
render={ ( { field } ) => (
<TextInput
{ ...field }
id="name"
placeholder="Enter a name for your project"
validated={ errors.name ? 'error' : 'default' }
isRequired></TextInput>
) }/>
</FormGroup>
</GridItem>
<GridItem>
<FormGroup
fieldId="description"
label="Description"
helperText="Describe the project"
helperTextInvalid={ errors.description?.message }
validated={errors.description ? 'error' : 'default' }>
<Controller
name="description"
control={ control }
render={ ( { field } ) => (
<TextArea
{ ...field }
id="description"
rows={ 3 }
validated={errors.description ? 'error' : 'default' }
placeholder="Enter a description for your project" />
)} />
</FormGroup>
</GridItem>
</Grid>
</CardBody>
<CardFooter>
<Button variant="primary" type="submit" isLoading={ isSaving } isDisabled={ !isValid || !isChanged || isSaving }>Save</Button>
<Button variant="plain" type="reset">Reset</Button>
</CardFooter>
</Card>
</Form>
</StackItem>
<StackItem>
<Card isRounded style={ { border: '1px solid var(--pf-global--danger-color--100)', overflow: 'hidden' } }>
<CardTitle className="pf-u-danger-color-100">Advanced Settings</CardTitle>
<Menu style={ { boxShadow: 'none' } }>
<MenuContent>
<MenuList>
<MenuItem
description="Transfer this project to another user"
itemId={ 0 }
onClick={ handleOwnershipTransferToggle }
actions={
<MenuItemAction
actionId="transfer"
icon={ <ion-icon name="swap-horizontal-outline"></ion-icon> }
aria-label="Transfer ownership" />
}>
Transfer ownership
</MenuItem>
<MenuItem
description="Deletes the app from One Platform. Cannot be reverted."
itemId={ 1 }
onClick={ () => history.push( { search: 'action=delete' } ) }
actions={
<MenuItemAction
actionId="delete"
icon={ <ion-icon class="pf-u-danger-color-100" name="trash" /> }
aria-label="Delete the app" />
}>
<span className="pf-u-danger-color-100">Delete this App</span>
</MenuItem>
</MenuList>
</MenuContent>
</Menu>
</Card>
</StackItem>
</Stack>
<Modal
variant="small"
isOpen={ isDeleteModalOpen }
aria-label="Delete App Modal"
title="Are you sure?"
titleIconVariant="danger"
showClose={ true }
onClose={ handleModalClose }>
<Text>This action is irreversible and will permanently delete the <strong><em>{ app.name }</em></strong> app from One Platform.</Text>
<br />
<Form onSubmit={ handleDeleteApp }>
<FormGroup fieldId="delete-app" label={ `Please type "${ app.name }" to confirm` } isRequired>
<TextInput id="delete-app" autoFocus onChange={ val => setDeleteAppConformation( val ) } isRequired></TextInput>
</FormGroup>
<Button variant="danger" type="submit" isDisabled={ app.name !== deleteAppConfirmation }>I understand the consequences, delete this app</Button>
</Form>
</Modal>
</>
);
}
Example #8
Source File: AlertDismissForm.tsx From backstage with Apache License 2.0 | 4 votes |
AlertDismissForm = forwardRef<
HTMLFormElement,
AlertDismissFormProps
>(({ onSubmit, disableSubmit }, ref) => {
const classes = useStyles();
const [other, setOther] = useState<Maybe<string>>(null);
const [feedback, setFeedback] = useState<Maybe<string>>(null);
const [reason, setReason] = useState<AlertDismissReason>(
AlertDismissReason.Resolved,
);
const onFormSubmit: FormEventHandler = e => {
e.preventDefault();
if (reason) {
onSubmit({
other: other,
reason: reason,
feedback: feedback,
});
}
};
const onReasonChange = (_: ChangeEvent<HTMLInputElement>, value: string) => {
if (other) {
setOther(null);
}
setReason(value as AlertDismissReason);
};
const onOtherChange = (e: ChangeEvent<HTMLInputElement>) => {
return e.target.value
? setOther(e.target.value as AlertDismissReason)
: setOther(null);
};
const onFeedbackChange = (e: ChangeEvent<HTMLInputElement>) => {
return e.target.value
? setFeedback(e.target.value as AlertDismissReason)
: setFeedback(null);
};
useEffect(() => {
function validateDismissForm() {
if (reason === AlertDismissReason.Other) {
if (other) {
disableSubmit(false);
} else {
disableSubmit(true);
}
} else if (reason) {
disableSubmit(false);
} else {
disableSubmit(true);
}
}
validateDismissForm();
}, [reason, other, disableSubmit]);
return (
<form ref={ref} onSubmit={onFormSubmit}>
<FormControl component="fieldset" fullWidth>
<Typography color="textPrimary">
<b>Reason for dismissing?</b>
</Typography>
<Box mb={1}>
<RadioGroup
name="dismiss-alert-reasons"
value={reason}
onChange={onReasonChange}
>
{AlertDismissOptions.map(option => (
<FormControlLabel
key={`dismiss-alert-option-${option.reason}`}
label={option.label}
value={option.reason}
control={<Radio className={classes.radio} />}
/>
))}
</RadioGroup>
<Collapse in={reason === AlertDismissReason.Other}>
<Box ml={4}>
<TextField
id="dismiss-alert-option-other"
variant="outlined"
multiline
fullWidth
rows={4}
value={other ?? ''}
onChange={onOtherChange}
/>
</Box>
</Collapse>
</Box>
<Typography gutterBottom>
<b>Any other feedback you can provide?</b>
</Typography>
<TextField
id="dismiss-alert-feedback"
variant="outlined"
multiline
rows={4}
fullWidth
value={feedback ?? ''}
onChange={onFeedbackChange}
/>
</FormControl>
</form>
);
})
Example #9
Source File: GamepadConfigEditor.tsx From xcloud-keyboard-mouse with GNU General Public License v3.0 | 4 votes |
function GamepadConfigEditor({ name, onSubmitChanges, onCancelCreate, onActivate, onDelete }: SensitivityEditorProps) {
const { status, config: storedGamepadConfig } = useAppSelector((state) => getGamepadConfig(state, name));
const isActive = useAppSelector((state) => isConfigActive(state, name));
const isSubmitting = status === 'writing';
const isNewDraft = !storedGamepadConfig;
const isDefaultConfig = name === DEFAULT_CONFIG_NAME;
const initialGamepadConfig = storedGamepadConfig || emptyGamepadConfig;
const [state, dispatch] = useKeyConfigEditorState(initialGamepadConfig);
const noMouse = state.config.mouseConfig.mouseControls === undefined;
const hasChanges = isNewDraft || state.changes.keyConfig || state.changes.mouseConfig;
// Starts in read-only state, but have button to enable editing/save changes?
const [isEditing, setIsEditing] = useState(isNewDraft);
useEffect(() => {
if (isNewDraft) {
setIsEditing(true);
} else {
setIsEditing(false);
}
dispatch({ type: 'reset', config: initialGamepadConfig });
}, [dispatch, name, isNewDraft, initialGamepadConfig]);
const handleKeybindChange = useCallback(
(button: string, updated: KeyMap) => {
dispatch({
type: 'updateKeyConfig',
button,
keyMap: updated,
});
},
[dispatch],
);
const handleMouseControlsChange = useCallback(
(mouseControls?: StickNum) => {
dispatch({
type: 'updateMouseControls',
mouseControls,
});
},
[dispatch],
);
const handleActivate = useCallback(() => {
onActivate(name);
}, [name, onActivate]);
const handleToggleEditing = useCallback(() => {
if (isNewDraft && isEditing) {
if (confirm('Are you sure you want to cancel creating a new preset?')) {
onCancelCreate();
}
return;
}
if (isEditing && (!hasChanges || confirm('Are you sure you want to cancel? You will lose any changes.'))) {
// Reset
dispatch({ type: 'reset', config: storedGamepadConfig });
setIsEditing(!isEditing);
} else if (!isEditing) {
setIsEditing(!isEditing);
}
}, [dispatch, hasChanges, isEditing, isNewDraft, onCancelCreate, storedGamepadConfig]);
const handleDelete = useCallback(() => {
if (confirm('Are you sure you want to delete this preset?')) {
onDelete(name);
}
}, [name, onDelete]);
const handleExport = useCallback(() => {
exportConfig(state.config, name);
}, [state.config, name]);
const handleSubmit: FormEventHandler<HTMLFormElement> = useCallback(
(e) => {
e.preventDefault();
if (!state.errors.hasErrors) {
onSubmitChanges(name, state.config);
} else {
console.error('Cannot submit', state.errors);
}
},
[name, onSubmitChanges, state.config, state.errors],
);
return (
<form className="vertical full-height" onSubmit={handleSubmit}>
<section className="config-editor full-absolute vertical">
<table className="margin-vertical">
<tbody>
{(Object.keys(emptyGamepadConfig.keyConfig) as Array<keyof typeof state.config.keyConfig>).map((button) => {
const val = state.config.keyConfig[button];
return (
<KeybindingsForButton
key={button.toString()}
useSpacers
button={button}
readOnly={!isEditing}
value={val}
onChange={handleKeybindChange}
error={state.errors.keyConfig[button]}
/>
);
})}
</tbody>
</table>
<div className="margin-bottom">
<div className="horizontal">
<StickSelector
readOnly={!isEditing}
onChange={handleMouseControlsChange}
stick={state.config.mouseConfig.mouseControls}
/>
</div>
<SensitivitySelector
dispatch={dispatch}
disabled={noMouse}
readOnly={!isEditing}
sensitivity={state.config.mouseConfig.sensitivity}
/>
</div>
</section>
<section className="horizontal space-between padding-top-s">
<div className="margin-right-s">
<DefaultButton onClick={handleToggleEditing}>{isEditing ? 'Cancel' : 'Edit'}</DefaultButton>
{!isEditing ? (
<DefaultButton className="margin-left-s" disabled={isDefaultConfig} onClick={handleDelete}>
Delete
</DefaultButton>
) : null}
{!isEditing ? (
<DefaultButton className="margin-left-s" onClick={handleExport}>
Export
</DefaultButton>
) : null}
</div>
{isEditing ? (
<PrimaryButton type="submit" disabled={state.errors.hasErrors || !hasChanges || isSubmitting}>
{isNewDraft ? 'Create' : 'Save'}
</PrimaryButton>
) : (
<PrimaryButton onClick={handleActivate} disabled={state.errors.hasErrors || isActive || isSubmitting}>
Use
</PrimaryButton>
)}
</section>
</form>
);
}
Example #10
Source File: EmailSignup.tsx From oxen-website with GNU General Public License v3.0 | 4 votes |
export default function EmailSignup(props: Props): ReactElement {
const { classes } = props;
const router = useRouter();
const buttonRef = useRef<HTMLButtonElement>(null);
const setButtonText = (value: string) => {
if (null !== buttonRef.current) {
buttonRef.current.innerText = value;
}
};
const [email, setEmail] = useState('');
const handleSubscription: FormEventHandler = async event => {
event.preventDefault();
setButtonText('Subscribing...');
let response;
try {
response = await fetch('/api/email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
});
} catch (error) {
response = error;
}
switch (response?.status) {
case 201:
setEmail('');
setButtonText('Signed up ✓');
break;
case 400:
default:
setButtonText('Signup failed ✗');
break;
}
};
return (
<Contained
id="signup"
classes={classNames(
'border-2 border-solid border-primary py-6 px-2 mt-6 mb-10',
'tablet:w-4/5 tablet:mx-auto tablet:py-4 tablet:mt-6 tablet:mb-8',
'desktop:py-6',
router.asPath !== '/get-involved' && 'tablet:w-full',
classes,
)}
>
<h3
className={classNames(
'text-2xl font-semibold leading-none mb-2',
'tablet:text-3xl',
'desktop:text-4xl desktop:mb-3',
)}
>
You've got mail!
</h3>
<p
className={classNames(
'leading-none mb-6',
'tablet:mb-3 tablet:leading-tight',
'desktop:mb-6 desktop:text-xl',
)}
>
Sign up to our newsletter to keep up to date with everything Oxen.
</p>
<form onSubmit={handleSubscription}>
<Input
type="email"
placeholder="Your Email"
value={email}
onValueChange={value => setEmail(value)}
size={'large'}
border={'primary'}
inputMode={'text'}
className={classNames(
'mb-6 rounded-sm',
'tablet:mb-4',
'desktop:mb-6',
)}
required
/>
<Button
color="primary"
size="medium"
className={classNames('mx-auto', 'tablet:w-40')}
buttonType={'submit'}
reference={buttonRef}
>
Sign up
</Button>
</form>
</Contained>
);
}