reactjstypescriptoffice-jsoffice-ui-fabricoffice-js-helpers

Add Dynamic TextFields Through Dropdown Component Selection?


In the following project, I am creating a Task Pane using TypeScript and React in Microsoft Excel. When the Task Pane loads, it will only have a basic Dropdown with a few options. Folder Path

AppPic.tsx

import * as React from "react";
import Progress from "./Progress";
import { Dropdown, DropdownMenuItemType, IDropdownStyles, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
//import TopLevel from "./Operations/TopLevel";
//import MakeItem from "./Operations/MakeItem";
//import RawMaterial from "./Operations/RawMaterial";
//import BuyItem from "./Operations/BuyItem";
export interface AppProps {
  title: string;
  isOfficeInitialized: boolean;
}

export interface AppState {

}

export default class App extends React.Component<AppProps, AppState> {
  constructor(props, context) {
    super(props, context);
    this.state = {
    };
  }

  componentDidMount() {
    this.setState({

    });
  }

  render() {
    const { title, isOfficeInitialized } = this.props;
    const dropdownStyles: Partial<IDropdownStyles> = {
      dropdown: { width: 300 }
    };
    const options: IDropdownOption[] = [
      { key: 'blank', text: '' },
      { key: 'topLevelMake', text: 'Parents', itemType: DropdownMenuItemType.Header },
      { key: 'topLevel', text: 'TOP LEVEL' },
      { key: 'make', text: 'MAKE ITEM' },
      { key: 'divider_1', text: '-', itemType: DropdownMenuItemType.Divider },
      { key: 'Purchased', text: 'Purchases', itemType: DropdownMenuItemType.Header },
      { key: 'rawMaterial', text: 'RAW MATERIAL' },
      { key: 'buyItem', text: 'BUY ITEM' },
    ];
    ;
    if (!isOfficeInitialized) {
      return (
        <Progress title={title} logo="assets/logo-filled.png" message="Please sideload your addin to see app body." />
      );
    }

    return (
      <div className="ms-welcome">
            <Dropdown
              label="Operation"
              key="dropDownKey"
              options={options}
              styles={dropdownStyles}
            />
      </div>
    );
  }
}

After the response from Klas, I have changed my code around a bit, but am having troubles because there are no errors thrown around. I have my App.tsx, my TopLevel.tsx, and the new file I created because of Klas called Dropdown.tsx. For now i will forget about "Make", I am just trying to understand the logic. What am i doing wrong here?

App.tsx

import * as React from "react";
import Dropdown from "./Operations/Dropdown";
export interface AppProps {
  title: string;
  isOfficeInitialized: boolean;
}
export interface AppState {

}

function App() {
  return <Dropdown />;
}

export default App;

Dropdown.tsx

import * as React from "react";
import TopLevel from './TopLevel';
import { useState } from 'react';
const Dropdown = (): React.ReactElement => {
    const [value, setValue] = useState("none");
    let Form: any;
    switch (value) {
      case "TopLevel":
        Form = <TopLevel title="title" logo="logo" message="message" />;
        break;

      case "Make":
        Form = <div />;
        break;

      default:
        Form = <div />;
        break;
    }
    return (
      <div>
        <select
          id="lang"
          onChange={event => event?.target?.value && setValue(event.target.value)}
          value={value}
        >
          <option value="select">Select</option>
          <option value="TopLevel">TopLevel</option>
          <option value="Make">Make</option>
        </select>
        {Form}
      </div>
    );
  };
  export default Dropdown;

TopLevel.tsx

import * as React from "react";

export interface TopLevelProps {
  title: string;
  logo: string;
  message: string;
}
export default class TopLevel extends React.Component<TopLevelProps> {
  render() {
    return (
      <div>
        <div>TopLevel</div>
        <input placeholder="Part Number" />
      </div>
    );
  }
}

Here is the error that I am getting. enter image description here


Solution

  • Here is a basic program that has a dropdown and will show different forms based on the value of the dropdown.

    const Dropdown = (): React.ReactElement => {
      const [value, setValue] = useState("none");
    
      let Form: any;
      switch (value) {
        case "TopLevel":
          Form = <TopLevel title="title" logo="logo" message="message" />;
          break;
    
        case "Make":
          Form = <Make />;
          break;
    
        default:
          Form = <div />;
          break;
      }
    
      return (
        <div>
          <select
            id="lang"
            onChange={event => event?.target?.value && setValue(event.target.value)}
            value={value}
          >
            <option value="select">Select</option>
            <option value="TopLevel">TopLevel</option>
            <option value="Make">Make</option>
          </select>
          {Form}
        </div>
      );
    };
    
    export interface TopLevelProps {
      title: string;
      logo: string;
      message: string;
    }
    
    class TopLevel extends React.Component<TopLevelProps> {
      render() {
        return (
          <div>
            <div>TopLevel</div>
            <input placeholder="Part Number" />
          </div>
        );
      }
    }
    
    class Make extends React.Component<{}> {
      render() {
        return <div>Make</div>;
      }
    }
    
    function App() {
      return <Dropdown />;
    }
    

    Note how the switch lets you have different forms for different values.

    The DropDown component you are using also has an onChange property, so that should be possible to wire up in a similar way, with different form renderings for different values.