Skip to content
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

Custom form fields #760

Merged
merged 10 commits into from
Nov 23, 2023
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [0.36.0] - 2023-10-30

### Added

- Introduced the capability to utilize custom components in the Email-Password based recipes' signup form fields by exposing inputComponent types.
- Implemented the functionality to assign default values to the form fields in the Email-Password based recipes.
- Simplified onChange prop usage in inputComponent - id attribute removed.

Following is an example of how to use above features.

```tsx
EmailPassword.init({
amitbadala marked this conversation as resolved.
Show resolved Hide resolved
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "select-dropdown",
label: "Select Option",
getDefaultValue: () => "option 2",
inputComponent: ({ value, name, onChange }) => (
<select
value={value}
name={name}
onChange={(e) => onChange(e.target.value)}
placeholder="Select Option">
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
},
],
},
},
});
```

## [0.35.6] - 2023-10-16

### Test changes
Expand Down
219 changes: 216 additions & 3 deletions examples/for-tests/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,167 @@ const formFields = [
},
];

const formFieldsWithDefault = [
{
id: "country",
label: "Your Country",
placeholder: "Where do you live?",
optional: true,
getDefaultValue: () => "India",
},
{
id: "select-dropdown",
label: "Select Option",
getDefaultValue: () => "option 2",
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
getDefaultValue: () => "true",
inputComponent: ({ name, onChange, value }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input
value={value}
checked={value === "true"}
name={name}
type="checkbox"
onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
{
id: "email",
label: "Email",
getDefaultValue: () => "[email protected]",
},
{
id: "password",
label: "Password",
getDefaultValue: () => "fakepassword123",
},
];

const incorrectFormFields = [
{
id: "country",
label: "Your Country",
placeholder: "Where do you live?",
optional: true,
getDefaultValue: () => 23, // return should be a string
},
{
id: "select-dropdown",
label: "Select Dropdown",
getDefaultValue: "option 2", // should be function
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
// onChange accepts only string value, here we pass boolean
id: "terms",
label: "",
optional: false,
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked)}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
{
id: "city",
label: "Your city",
optional: false,
nonOptionalErrorMsg: "", // empty string should throw error
},
];

const customFields = [
{
id: "select-dropdown",
label: "Select Dropdown",
nonOptionalErrorMsg: "Select dropdown is not an optional",
inputComponent: ({ value, name, onChange }) => (
<select value={value} name={name} onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
nonOptionalErrorMsg: "You must accept the terms and conditions",
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>I agree to the terms and conditions</span>
</div>
),
validate: async (value) => {
if (value === "true") {
return undefined;
}
return "Please check Terms and conditions";
},
},
];

const testContext = getTestContext();

let recipeList = [
Expand Down Expand Up @@ -552,6 +713,55 @@ function getEmailVerificationConfigs({ disableDefaultUI }) {
});
}

function getFormFields() {
porcellus marked this conversation as resolved.
Show resolved Hide resolved
if (localStorage.getItem("SHOW_INCORRECT_FIELDS") === "YES") {
porcellus marked this conversation as resolved.
Show resolved Hide resolved
if (localStorage.getItem("INCORRECT_ONCHANGE") === "YES") {
// since page-error blocks all the other errors
// use this filter to test specific error
return incorrectFormFields.filter(({ id }) => id === "terms");
} else if (localStorage.getItem("INCORRECT_NON_OPTIONAL_ERROR_MSG") === "YES") {
return incorrectFormFields.filter(({ id }) => id === "city");
} else if (localStorage.getItem("INCORRECT_GETDEFAULT") === "YES") {
return incorrectFormFields.filter(({ id }) => id === "country");
}
return incorrectFormFields;
} else if (localStorage.getItem("SHOW_CUSTOM_FIELDS_WITH_DEFAULT_VALUES") === "YES") {
return formFieldsWithDefault;
} else if (localStorage.getItem("SHOW_CUSTOM_FIELDS") === "YES") {
return customFields;
}
return formFields;
}

function getSignInFormFields() {
porcellus marked this conversation as resolved.
Show resolved Hide resolved
let showDefaultFields = localStorage.getItem("SHOW_SIGNIN_DEFAULT_FIELDS");
let showFieldsWithNonOptionalErrMsg = localStorage.getItem("SHOW_SIGNIN_WITH_NON_OPTIONAL_ERROR_MESSAGE");
if (showDefaultFields === "YES") {
return {
formFields: [
{
id: "email",
getDefaultValue: () => "[email protected]",
},
{
id: "password",
getDefaultValue: () => "fakepassword123",
},
],
};
} else if (showFieldsWithNonOptionalErrMsg === "YES") {
return {
formFields: [
{
id: "email",
nonOptionalErrorMsg: "Please add email",
},
],
};
}
return {};
}

function getEmailPasswordConfigs({ disableDefaultUI }) {
return EmailPassword.init({
style: `
Expand Down Expand Up @@ -632,12 +842,13 @@ function getEmailPasswordConfigs({ disableDefaultUI }) {
defaultToSignUp,
signInForm: {
style: theme,
...getSignInFormFields(),
},
signUpForm: {
style: theme,
privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
formFields,
formFields: getFormFields(),
},
},
});
Expand Down Expand Up @@ -1160,9 +1371,11 @@ function getThirdPartyEmailPasswordConfigs({ staticProviderList, disableDefaultU
},
signInAndUpFeature: {
disableDefaultUI,
signInForm: {},
signInForm: {
...getSignInFormFields(),
},
signUpForm: {
formFields,
formFields: getFormFields(),
privacyPolicyLink: "https://supertokens.com/legal/privacy-policy",
termsOfServiceLink: "https://supertokens.com/legal/terms-and-conditions",
},
Expand Down
7 changes: 7 additions & 0 deletions lib/build/emailpassword-shared4.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading