Subform example
Consider following example. It is required to enter address
information in different places in the UI. For example address
of the user, address of the order, address of the store and so on.
It is good idea to create address form and reuse it in several places.
This is where useSubform come into play. It accepts rffFormControl from
parent form and generate rffFormControl for subform.
Consider following entities.
type Order = {
orderNo : number ;
carrier : string ;
deliveryAddress : {
country : string ;
state : string ;
city : string ;
zipCode : string ;
street1 : string ;
street2 ?: string | undefined ;
};
};
type Store = {
name : string
location : {
country : string ;
state : string ;
city : string ;
zipCode : string ;
street1 : string ;
street2 ?: string | undefined ;
}
}
To modify deliveryAddress.country we can use
< Field
rffFormControl ={ rffFormControl }
rffName = "deliveryAddress.country"
rffComponent ={ Input }
/>
But this way country input will be bound to Order and cannot be used
with address of the Store. useSubform solves this problem.
const addressrffFormControl = useSubform ({
rffFormControl,
rffName: 'deliveryAddress' ,
})
return (
< Field
rffFormControl ={ addressrffFormControl }
rffName = "country"
rffComponent ={ Input }
/>
)
Input for country is not bound to the Order and can be reused
with other forms.
Example OrderForm.tsx AddressForm.tsx
const addressFormControl = useSubform ({
formControl,
name: "deliveryAddress" ,
});
// ... Other code ...
< AddressForm subFormControl ={ addressFormControl } /> import { Field, FormControl } from "react-flexible-form" ;
import * as Yup from "yup" ;
import { FC } from "react" ;
import SimpleInput from "./SimpleInput" ;
export type Address = {
country : string ;
state : string ;
city : string ;
zipCode : string ;
street1 : string ;
street2 ?: string | undefined ;
};
export const addressValidator = Yup. object ({
country: Yup. string (). required ( "Required" ),
state: Yup. string (). required ( "Required" ),
city: Yup. string (). required ( "Required" ),
zipCode: Yup. string (). required ( "Required" ),
street1: Yup. string (). required ( "Required" ),
street2: Yup. string (),
});
type Props = {
subFormControl : Omit < FormControl < Address >, "handleSubmit" >;
};
const AddressForm : FC < Props > = ({ subFormControl }) => {
return (
< div
style ={ {
width: "100%" ,
display: "grid" ,
gridTemplateRows: "repeat(4, auto)" ,
gridTemplateColumns: "auto auto" ,
gap: "10px" ,
} }
>
< Field
rffFormControl ={ subFormControl }
rffName = "country"
rffComponent ={ SimpleInput }
label = "Country"
style ={ { gridColumn: 1 , gridRow: 1 } }
/>
< Field
rffFormControl ={ subFormControl }
rffName = "state"
rffComponent ={ SimpleInput }
label = "State"
style ={ { gridColumn: 1 , gridRow: 2 } }
/>
< Field
rffFormControl ={ subFormControl }
rffName = "city"
rffComponent ={ SimpleInput }
label = "City"
style ={ { gridColumn: 1 , gridRow: 3 } }
/>
< Field
rffFormControl ={ subFormControl }
rffName = "zipCode"
rffComponent ={ SimpleInput }
label = "Zip Code"
style ={ { gridColumn: 2 , gridRow: 1 } }
/>
< Field
rffFormControl ={ subFormControl }
rffName = "street1"
rffComponent ={ SimpleInput }
label = "Street Address 1"
style ={ { gridColumn: 2 , gridRow: 2 } }
/>
< Field
rffFormControl ={ subFormControl }
rffName = "street2"
rffComponent ={ SimpleInput }
label = "Street Address 2"
style ={ { gridColumn: 2 , gridRow: 3 } }
/>
</ div >
);
};
export default AddressForm;