In the following Parent component, I have a Dropdown with two options. If you select "TOP LEVEL", then a form called Form1 will show. If I choose "MAKE ITEM" then a form called Form2 will show. If nothing is selected then both forms are hidden. I have a Button in my Parent component and I want to submit whatever inputs are in the current form that is shown. So if "TOP LEVEL" was selected, and the Button is clicked, I want to log the input's from Form1. Is this possible to do? Or do I need to put everything into one component? If this is possible, do I need to use Formik? If I am approaching this wrong please advise a better way.
Parent Component
import * as React from "react";
import { Dropdown, DropdownMenuItemType, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { PrimaryButton } from 'office-ui-fabric-react/lib/';
import Form1 from './Form1';
import Form2 from './Form2';
export interface ParentProps {
};
export interface ParentState {
selectedItem?: { key: string | number | undefined };
operationType?;
formName?
};
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
};
}
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log(`The range address was ${range.address}.`);
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
})
};
render(){
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return(
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({operationType: item.text})
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 /> ;
this.setState({formName: Form});
break;
case "MAKE ITEM":
Form = <Form2 /> ;
this.setState({formName: Form});
break;
default:
Form = <div></div>
break;
}
};
}
Form1 (Form2 is similar so I am not including)
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
};
export interface Form1State {
dataGoToExcel?;
dataGoToExcel2?;
};
export default class Form1 extends React.Component<Form1Props, Form1State> {
constructor(props, context) {
super(props, context);
this.state = {
dataGoToExcel: '',
dataGoToExcel2: '',
};
}
handleChange = (event) => {
this.setState({
dataGoToExcel: event.target.value,
})
};
handleChange2 = (event) => {
this.setState({
dataGoToExcel2: event.target.value,
})
};
render(){
return(
<div>
<TextField
label="TextField"
type="text"
value={this.state.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.state.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
EDIT:
Parent
import * as React from "react";
import { Dropdown, DropdownMenuItemType, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { PrimaryButton } from 'office-ui-fabric-react/lib/';
import Form1 from './Form1';
//import Form2 from './Form2';
export interface ParentProps {
};
export interface ParentState {
selectedItem?: { key: string | number | undefined };
operationType?;
formName?;
formData;
updateFormData?;
};
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
formData: ''
};
}
updateFormData = (data) => this.setState({ formData: data })
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log((`The range address was ${this.state.formData}.`))
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
formData: '',
formName: '',
})
};
render() {
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return (
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({ operationType: item.text })
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
//case "MAKE ITEM":
// Form = <Form2 formData={this.state.formName} onDataChange={this.updateFormData} />;
// this.setState({ formName: Form });
// break;
default:
Form = <div></div>
break;
}
};
}
Form1 (commented out Form2)
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
formData: any /* Type of form data */
onDataChange: (data: any) => void
};
export default class Form1 extends React.Component<Form1Props> {
handleChange = (event: any) => {
const data = this.props.formData & event.target.value; /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
handleChange2 = (event: any) => {
const data = this.props.formData & event.target.value;/* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
render(){
return (
<div>
<TextField
label="TextField"
type="text"
value={this.props.formData.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.props.formData.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};
One way to do this is to
Finally, when the button in Parent is clicked, the contents from the state can be submitted.
You'll have to move up local states from Form1 and Form2 into parent and send pass necessary form values as props to child components and no local states for the child components would be needed
EDIT:
Parent Component
export default class ParentComponent extends React.Component<ParentProps, ParentState> {
constructor(props, context) {
super(props, context);
this.state = {
operationType: '',
formName: '',
formData: {/*data as object*/ }
};
}
updateFormData = (data) => this.setState({ formData: data })
addToExcel = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.getSelectedRange();
range.load("address");
await context.sync();
console.log(`The range address was ${range.address}.`);
});
} catch (error) {
console.error(error);
}
this.setState({
operationType: '',
})
};
render() {
const { selectedItem } = this.state;
const options: IDropdownOption[] = [
{ key: 'blank', text: '' },
{ key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
{ key: 'topLevel', text: 'TOP LEVEL' },
{ key: 'make', text: 'MAKE ITEM' },
];
return (
<div>
<Dropdown
label="Operation"
selectedKey={selectedItem ? selectedItem.key : undefined}
onChange={this._onChange}
placeholder={"Select an option"}
options={options}
styles={{ dropdown: { width: 300 } }}
/>
{this.state.formName}
<p></p>
<PrimaryButton
text="Enter"
onClick={this.addToExcel}
/>
</div>
);
}
private _onChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
this.setState({ selectedItem: item });
this.setState({ operationType: item.text })
console.log(event);
let Form = <div />;
switch (item.text) {
case "TOP LEVEL":
Form = <Form1 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
case "MAKE ITEM":
Form = <Form2 formData={this.state.formData} onDataChange={this.updateFormData} />;
this.setState({ formName: Form });
break;
default:
Form = <div></div>
break;
}
};
}
Form 1 Component
import * as React from "react";
import { TextField } from 'office-ui-fabric-react/lib/';
export interface Form1Props {
formData: any /* Type of form data */
onDataChange: (data: any) => void
};
export default class Form1 extends React.Component<Form1Props> {
handleChange = (event) => {
const data = /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
handleChange2 = (event) => {
const data = /* merge props.formdata and event.target.value*/
this.props.onDataChange(data)
};
render(){
return (
<div>
<TextField
label="TextField"
type="text"
value={this.props.formData.dataGoToExcel}
onChange={this.handleChange}
/>
<TextField
label="Another TextField"
type="text"
value={this.props.formData.dataGoToExcel2}
onChange={this.handleChange2}
/>
</div>
);
}
};