Search code examples
reactjsoffice-ui-fabricoffice-ui-fabric-reactfluent-ui

read the Form component from @fluentui/[email protected]


There is a nice looking schema-based Form component on fluentui

import React from 'react';
import { Form, Button } from '@fluentui/react-northstar';

const fields = [
  {
    label: 'First name',
    name: 'firstName',
    id: 'first-name-shorthand',
    key: 'first-name',
    required: true,
  },
  {
    label: 'Last name',
    name: 'lastName',
    id: 'last-name-shorthand',
    key: 'last-name',
    required: true,
  },
  {
    label: 'I agree to the Terms and Conditions',
    control: {
      as: 'input',
    },
    type: 'checkbox',
    id: 'conditions-shorthand',
    key: 'conditions',
  },
  {
    control: {
      as: Button,
      content: 'Submit',
    },
    key: 'submit',
  },
];

const FormExample = () => (
  <Form
    onSubmit={() => {
      alert('Form submitted');
    }}
    fields={fields}
  />
);

export default FormExample;

But they don't offer any method/example to collect the data from what I can tell. (at least not in the documentation). I can collect most values from the onSubmit event but it get's hacky because not all html components are necessarily input elements that have the value attribute. I also don't think this is the intended way to do it. Anyone can enlighten me please? I think you must be able to feed the onChange function to it somehow. Or am i supposed to add the onChange function in each field-object?


Solution

  • I ended up combing through the library components (Forms Input and Checkbox) to see what makes them tick.

    This is what I ended up with. Please feel free to improve on it should anyone else stumble on this in the future.

    Note the use of the attributes defaultValue and defaultChecked to set the initial value of the Input and Checkbox components respectively. As well as the onChange event passing the name and value parameters for the Input component and name and checked for the Checkbox component.

    The Checkbox label must be inside the Control if you wish it to appear next to the checkbox, otherwise it will appear above the checkbox.

    import React, { Component } from 'react';
    import { Form, Button, Checkbox, Input } from '@fluentui/react-northstar';
    
    class Login extends Component {
      constructor(props) {
        super(props);
        this.handleSubmit.bind(this)
      }
      state = {
        email: "",
        password: "",
        remember_me: true
      }
      fields = [
        {
          label: 'Email',
          name: 'email',
          id: 'email-inline-shorthand',
          key: 'email',
          required: true,
          inline: true,
          type: 'email',
          control: {
            as: Input,
            defaultValue: this.state.email,
            onChange: (e, { name, value }) => this.setState({ ...this.state, [name]: value })
          }
        },
        {
          label: 'Password',
          name: 'password',
          id: 'password-inline-shorthand',
          key: 'password',
          required: true,
          inline: true,
          type: 'password',
          control: {
            defaultValue: this.state.password,
            onChange: (e, { name, value }) => this.setState({ ...this.state, [name]: value }),
            as: Input,
          }
        },
        {
          name: "remember_me",
          key: 'remember_me',
          id: 'remember_me-inline-shorthand',
          type: 'boolean',
          control: {
            label: 'Remember me',
            as: Checkbox,
            defaultChecked: !!this.state.remember_me,
            onChange: (e, { name, checked }) => { this.setState({ ...this.state, [name]: checked }) }
          },
        },
        {
          control: {
            as: Button,
            content: 'Submit',
          },
          key: 'submit',
        },
      ]
    
      handleSubmit = (e) => {
        console.log("submitting these values", this.state)
      }
    
      render() {
        return (
          <Form
            onSubmit={this.handleSubmit}
            fields={this.fields}
          />
        )
      }
    };
    
    export default Login;