Получить входные данные от дочерней компонентной формы, которая не проходит реквизит? - PullRequest
0 голосов
/ 07 апреля 2020

В следующем родительском компоненте у меня есть раскрывающийся список с двумя вариантами. Если вы выберете «TOP LEVEL», появится форма Form1. Если я выберу «MAKE ITEM», появится форма Form2. Если ничего не выбрано, то обе формы скрыты. У меня есть кнопка в моем родительском компоненте, и я хочу отправить любые входные данные в текущей форме, которая отображается. Поэтому, если выбрано «TOP LEVEL» и нажата кнопка, я хочу записать входные данные из формы Form1. Возможно ли это сделать? Или мне нужно все поместить в один компонент? Если это возможно, мне нужно использовать Formik? Если я подхожу к этому неправильно, пожалуйста, посоветуйте лучший способ.

Родительский компонент

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;
    }
  };
}

Форма 1 (Форма 2 похожа, поэтому я не включаю)

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>
      );
   }
  };

РЕДАКТИРОВАТЬ :

Родитель

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;
    }
  };
}

Форма 1 (закомментированная Форма 2)

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>
    );
  }
};

1 Ответ

1 голос
/ 07 апреля 2020

Один из способов сделать это -

  • Иметь функцию, которая обновляет данные формы в родительское состояние
  • Передать эту функцию обеим формам 1 и 2 в качестве реквизитов.
  • Для любого обновления в формах эта функция должна вызываться для обновления родительского состояния
  • Эти обновленные значения также должны передаваться дочерним элементам в качестве реквизитов.

Наконец, когда нажата кнопка в Parent, содержимое из состояния может быть отправлено.

Вам нужно переместить локальные состояния из Form1 и Form2 вверх в родительский и отправить необходимые значения формы в качестве реквизитов дочерним компонентам, и нет потребуются локальные состояния для дочерних компонентов

РЕДАКТИРОВАТЬ:

Родительский компонент

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;
    }
  };
}

Компонент формы 1

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>
    );
  }
};

...