Categories
Material UI

Material UI — Transfer List

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add a transfer list with Material UI.

Transfer List

A transfer list lets us move one or more items between lists.

To use it, we can write:

import React from "react";
import Grid from "@material-ui/core/Grid";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import Checkbox from "@material-ui/core/Checkbox";
import Button from "@material-ui/core/Button";
import Paper from "@material-ui/core/Paper";

function not(a, b) {
  return a.filter(value => b.indexOf(value) === -1);
}

function intersection(a, b) {
  return a.filter(value => b.indexOf(value) !== -1);
}

export default function App() {
  const [checked, setChecked] = React.useState([]);
  const [left, setLeft] = React.useState([0, 1, 2, 3]);
  const [right, setRight] = React.useState([4, 5, 6, 7]);

  const leftChecked = intersection(checked, left);
  const rightChecked = intersection(checked, right);

  const handleToggle = value => () => {
    const currentIndex = checked.indexOf(value);
    const newChecked = [...checked];

    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

  setChecked(newChecked);
  };

  const handleAllRight = () => {
    setRight(right.concat(left));
    setLeft([]);
  };

  const handleCheckedRight = () => {
    setRight(right.concat(leftChecked));
    setLeft(not(left, leftChecked));
    setChecked(not(checked, leftChecked));
  };

  const handleCheckedLeft = () => {
    setLeft(left.concat(rightChecked));
    setRight(not(right, rightChecked));
    setChecked(not(checked, rightChecked));
  };

  const handleAllLeft = () => {
    setLeft(left.concat(right));
    setRight([]);
  };

  const customList = items => (
    <Paper>
      <List dense component="div" role="list">
        {items.map(value => {
          const labelId = `transfer-list-item-${value}-label`;

  return (
            <ListItem
              key={value}
              role="listitem"
              button
              onClick={handleToggle(value)}
            >
              <ListItemIcon>
                <Checkbox
                  checked={checked.indexOf(value) !== -1}
                  tabIndex={-1}
                  disableRipple
                  inputProps={{ "aria-labelledby": labelId }}
                />
              </ListItemIcon>
              <ListItemText id={labelId} primary={`item ${value + 1}`} />
            </ListItem>
          );
        })}
        <ListItem />
      </List>
    </Paper>
  );

  return (
    <Grid container spacing={2} justify="center" alignItems="center">
      <Grid item>{customList(left)}</Grid>
      <Grid item>
        <Grid container direction="column" alignItems="center">
          <Button
            variant="outlined"
            size="small"
            onClick={handleAllRight}
            disabled={left.length === 0}
            aria-label="move all right"
          >
            ≫
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={handleCheckedRight}
            disabled={leftChecked.length === 0}
            aria-label="move selected right"
          >
            &gt;
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={handleCheckedLeft}
            disabled={rightChecked.length === 0}
            aria-label="move selected left"
          >
            &lt;
          </Button>
          <Button
            variant="outlined"
            size="small"
            onClick={handleAllLeft}
            disabled={right.length === 0}
            aria-label="move all left"
          >
            ≪
          </Button>
        </Grid>
      </Grid>
      <Grid item>{customList(right)}</Grid>
    </Grid>
  );
}

We have a grid 2 lists side by side.

We added the list with the List component.

The left list is created with the customList component, which has a List with some items inside it.

Each item has its own checkbox so that’s we can check them off and move them.

The moving is done by a few functions.

The handleAllRight function moves everything to the right.

handleCheckedRight moves everything that’s checked to the right.

handleCheckedLeft moves the items that are check to the left list.

handleAllLeft moves all items to the left list.

The move is done by a few helper functions.

setLeft and setRight sets the items for the left and right respectively.

We concatenate the existing items with the ones that’s checked in each function.

setChecked is used to set the checked value of each item.

It only unchecks that values that are moved.

The example is simplified from the one at https://material-ui.com/components/transfer-list/

Conclusion

We can make a transfer list by following the Material UI example.

We make 2 lists with their own items.

The items are on each list are determined by the state.

Then we can move them by concatenating to the new list and removing them from the old list.

Categories
Material UI

Material UI — Text Field Customization

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add text fields with Material UI.

Sizes

We can change the size of a text field with the size prop.

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";

export default function App() {
  return (
    <div className="App">
      <TextField label="Size" id="small" defaultValue="Small" size="small" />
    </div>
  );
}

to add a text field with the size small .

Layout

We can layout our text fields our way.

To do that, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex",
    flexWrap: "wrap"
  },
  textField: {
    marginLeft: theme.spacing(1),
    marginRight: theme.spacing(1),
    width: "25ch"
  }
}));

export default function App() {
  const classes = useStyles();

return (
    <>
      <div>
        <TextField
          id="filled-full-width"
          label="Label"
          style={{ margin: 8 }}
          placeholder="Placeholder"
          helperText="Full width!"
          fullWidth
          margin="normal"
          InputLabelProps={{
            shrink: true
          }}
          variant="filled"
        />
        <TextField
          label="None"
          id="filled-margin-none"
          defaultValue="foo"
          className={classes.textField}
          helperText="foo"
        />
        <TextField
          label="Dense"
          style={{ margin: 3 }}
          id="filled-margin-dense"
          defaultValue="bar"
          className={classes.textField}
          helperText="bar"
          margin="dense"
        />
      </div>
    </>
  );
}

to add text fields.

We have one full-width text field at the top and 2 shorter ones at the bottom.

They have the usual props, which have the helperText for the hint.

margin have the margin.

We also have some styles to change the margins.

className have the class names.

placeholder have the placeholder for the text fields.

variant can be filled or not.

margin can be smaller than the default with dense .

Uncontrolled vs Controlled

Text fields can be uncontrolled, which means that it doesn’t have any state attached to it.

Or it can be controlled, which means that it has state attached to it.

To make a controlled text field, we can add the value and onChange props to the TextField .

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <TextField
          id="standard-name"
          label="Name"
          value={name}
          onChange={handleChange}
        />
      </div>
    </>
  );
}

We have the name state which is passed into the value prop.

And the handleChange function which is passed into the onChange prop.

Then when we type something in, the handleChange function will run and call setName to update the name state.

Components

A TextField is made of smaller components.

They include FormControl , Input , FilledInput , InputLabel , OutlinedInput and FormHelperText .

For instance, we can substitute a TextField with:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <Input id="input" value={name} onChange={handleChange} />
        </FormControl>
      </div>
    </>
  );
}

We have an Input for the input box and InputLabel for the label for the input box.

To add hint text, we can use the FormHelperText component:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
import FormHelperText from "@material-ui/core/FormHelperText";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <Input id="input" value={name} onChange={handleChange} />
          <FormHelperText>enter your name</FormHelperText>
        </FormControl>
      </div>
    </>
  );
}

We can also use the OutlinedInput and FilledInput components to add input boxes with those varieties:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import OutlinedInput from "@material-ui/core/OutlinedInput";
import InputLabel from "@material-ui/core/InputLabel";
import FormHelperText from "@material-ui/core/FormHelperText";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <OutlinedInput
            id="input"
            value={name}
            onChange={handleChange}
            label="Name"
          />
          <FormHelperText>enter your name</FormHelperText>
        </FormControl>
      </div>
    </>
  );
}

to add an input box with the outline to the box.

And we can use the FilledInput to add an input box with the background:

import React from "react";
import FormControl from "@material-ui/core/FormControl";
import FilledInput from "@material-ui/core/FilledInput";
import InputLabel from "@material-ui/core/InputLabel";
import FormHelperText from "@material-ui/core/FormHelperText";

export default function App() {
  const [name, setName] = React.useState("james");
  const handleChange = event => {
    setName(event.target.value);
  };
  return (
    <>
      <div>
        <FormControl>
          <InputLabel htmlFor="input">Name</InputLabel>
          <FilledInput id="input" value={name} onChange={handleChange} />
          <FormHelperText>enter your name</FormHelperText>
        </FormControl>
      </div>
    </>
  );
}

Conclusion

A TextField is composed of many form components.

Therefore, we can add those instead of a TextField .

We can also make a text field and controller input.

Categories
Material UI

Material UI — Text Field Basics

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add text fields with Material UI.

Text Field

Text fields are form controls to let users enter and edit text.

To add them, we use the TextField component.

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";

export default function App() {
  return (
    <div className="App">
      <TextField label="Standard" />
    </div>
  );
}

to add a basic text field.

label is displayed as the placeholder.

We can also add the variant prop to change the styling.

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";

export default function App() {
  return (
    <div className="App">
      <TextField label="filled" variant="filled" />
    </div>
  );
}

to add a text field with a background color.

Form Props

We can add the required prop to make the field required.

disabled disables the text field.

type has the input type.

helperText lets us show users hints.

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";

export default function App() {
  return (
    <div className="App">
      <TextField label="required" required helperText="required field" />
    </div>
  );
}

to add helper text to our field, which will be displayed at the bottom.

required adds an asterisk to the label to indicate that it’s required.

Validation

The error prop lets us toggle the error state.

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";

export default function App() {
  return (
    <div className="App">
      <TextField label="error" error />
    </div>
  );
}

to show a text field with errors in it.

It’ll be all red.

Select

The select prop makes the text field use the Select component internally.

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";
import MenuItem from "@material-ui/core/MenuItem";

const fruits = [
  { value: "apple", label: "Apple" },
  { value: "orange", label: "Orange" },
  { value: "grape", label: "Grape" }
];

export default function App() {
  const [fruit, setFruit] = React.useState("apple");

  const handleChange = event => {
    setFruit(event.target.value);
  };

  return (
    <div className="App">
      <TextField
        select
        label="Select"
        value={fruit}
        onChange={handleChange}
        helperText="Please select your fruit"
      >
        {fruits.map(option => (
          <MenuItem key={option.value} value={option.value}>
            {option.label}
          </MenuItem>
        ))}
      </TextField>
    </div>
  );
}

We create a dropdown with the TextField component.

label has the label.

value is the selected value.

onChange runs when we change the selection, which we can use to set the select value state.

Inside the TextField , we have the MenuItem components to display the options.

Icons

We can add icons to our TextFields .

For example, we can write:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
import AccountCircle from "@material-ui/icons/AccountCircle";

export default function App() {
  return (
    <div className="App">
      <Grid container spacing={1} alignItems="flex-end">
        <Grid item>
          <AccountCircle />
        </Grid>
        <Grid item>
          <TextField id="input-with-icon-grid" label="input" />
        </Grid>
      </Grid>
    </div>
  );
}

to add a text field beside an icon.

AccountCircle is the icon.

The TextField is to the right of it.

Input Adornments

We can use the InputAdornment component to add prefix, suffix or an action to an input.

For example, we can write:

import React from "react";
import clsx from "clsx";
import InputAdornment from "@material-ui/core/InputAdornment";
import TextField from "@material-ui/core/TextField";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles(theme => ({
  margin: {
    margin: theme.spacing(1)
  },
  textField: {
    width: "25ch"
  }
}));

export default function App() {
  const classes = useStyles();

  return (
    <div className="App">
      <TextField
        label="length"
        id="filled-start-adornment"
        className={clsx(classes.margin, classes.textField)}
        InputProps={{
          startAdornment: (
            <InputAdornment position="start">meters</InputAdornment>
          )
        }}
      />
    </div>
  );
}

We add a TextField with an InputAdornment .

position set to start which means that we add a prefix to the input.

It’ll be displayed on the left.

We have a class to add some margins between the prefix and the input box.

Conclusion

We can add text fields to let users enter text.

There are many options we can change to style it the way we want.

Also, we can icons and text beside the input box.

There are also styles for errors.

Categories
Material UI

Material UI — Switches

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add switches with Material UI.

Switches

Switches are toggles that let us set something on or off.

To add one, we use the Switch component.

For instance, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <Switch checked={checked} onChange={handleChange} name="checked" />
    </div>
  );
}

We set the checked prop with the checked state.

onChange has a function that runs when we click on the toggle.

event.target.checked has the checked value so that we use it to change the checked state.

We can change the color with the color prop.

For example, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <Switch
        color="primary"
        checked={checked}
        onChange={handleChange}
        name="checked"
      />
    </div>
  );
}

With the color prop, we changed the color.

primary is purple.

Also, we can disable it with the disabled prop.

For example, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <Switch
        disabled
        checked={checked}
        onChange={handleChange}
        name="checked"
      />
    </div>
  );
}

With the disabled prop, users can’t interact with it.

Switch with FormControlLabel

To add a label with the switch, we can use the FormControlLabel component.

For example, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";
import FormControlLabel from "@material-ui/core/FormControlLabel";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <FormControlLabel
        control={
          <Switch checked={checked} onChange={handleChange} name="checked" />
        }
        label="switch"
      />
    </div>
  );
}

to add a switch with a label to the right.

The label prop is the text for the label.

Switches with FormGroup

FormGroup s let us wrap a bunch of for,m controls into a group.

We can use these with switches.

For instance, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormLabel from "@material-ui/core/FormLabel";
import FormControl from "@material-ui/core/FormControl";
import FormGroup from "@material-ui/core/FormGroup";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <FormControl component="fieldset">
        <FormLabel component="legend">choose</FormLabel>
        <FormGroup>
          <FormControlLabel
            control={
              <Switch
                checked={checked}
                onChange={handleChange}
                name="checked"
              />
            }
            label="switch"
          />
        </FormGroup>
      </FormControl>
    </div>
  );
}

We have a FormGroup surrounding our FormControlLabel for the switch.

Sizes

We can change the size with the size prop.

For example, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormLabel from "@material-ui/core/FormLabel";
import FormControl from "@material-ui/core/FormControl";
import FormGroup from "@material-ui/core/FormGroup";

export default function App() {
  const [checked, setChecked] = React.useState();

  const handleChange = event => {
    setChecked(event.target.checked);
  };

  return (
    <div className="App">
      <FormControlLabel
        control={
          <Switch size="small" checked={checked} onChange={handleChange} />
        }
        label="Small"
      />
    </div>
  );
}

to add a small switch.

We set size to small to make it small.

Customizable Switch

We can customize our switch with our own classes.

For example, we can write:

import React from "react";
import Switch from "@material-ui/core/Switch";
import { makeStyles } from "@material-ui/core/styles";
import { yellow } from "@material-ui/core/colors";

const useStyles = makeStyles({
  switchBase: {
    color: yellow[300],
    "&$checked": {
      color: yellow[500]
    },
    "&$checked + $track": {
      backgroundColor: yellow[500]
    }
  },
  checked: {},
  track: {}
});

export default function App() {
  const classes = useStyles();

  return (
    <div className="App">
      <Switch
        focusVisibleClassName={classes.focusVisible}
        disableRipple
        classes={{
          root: classes.root,
          switchBase: classes.switchBase,
          thumb: classes.thumb,
          track: classes.track,
          checked: classes.checked
        }}
      />
    </div>
  );
}

to make a switch with our own classes.

We have an object with switchBase property with styles for the color when it’s checked.

We set the color to yellow if it’s checked.

The background is also set to yellow.

Then we use the useStyles hook to get the classes and apply them to our Switch .

We can also pass any props into our Switch component as we wish.

Conclusion

We can add switches with different styles to let us add toggles for users to use.

Categories
Material UI

Material UI — Radio Button Errors, Dropdowns and Sliders

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add radio buttons, dropdowns, and sliders with Material UI.

Show Error

To show errors with radio buttons, we can pass in an error prop to it.

For instance, we can write:

import React from "react";
import Radio from "@material-ui/core/Radio";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormLabel from "@material-ui/core/FormLabel";
import FormControl from "@material-ui/core/FormControl";
import FormHelperText from "@material-ui/core/FormHelperText";
import Button from "@material-ui/core/Button";
import RadioGroup from "@material-ui/core/RadioGroup";

export default function App() {
  const [value, setValue] = React.useState("");
  const [error, setError] = React.useState(false);
  const [helperText, setHelperText] = React.useState("");

  const handleRadioChange = event => {
    setValue(event.target.value);
    setHelperText(" ");
    setError(false);
  };

  const handleSubmit = event => {
    event.preventDefault();

    if (value === "2") {
      setHelperText("right");
      setError(false);
    } else if (value === "3") {
      setHelperText("wrong");
      setError(true);
    } else {
      setHelperText("Please select an option.");
      setError(true);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <FormControl component="fieldset" error={error}>
        <FormLabel component="legend">What's 1 + 1?</FormLabel>
        <RadioGroup name="quiz" value={value} onChange={handleRadioChange}>
          <FormControlLabel value="2" control={<Radio />} label="2" />
          <FormControlLabel value="3" control={<Radio />} label="3" />
        </RadioGroup>
        <FormHelperText>{helperText}</FormHelperText>
        <Button type="submit" variant="outlined" color="primary">
          Check Answer
        </Button>
      </FormControl>
    </form>
  );
}

We have the value state to set the value that the user selects as the value.

In App , we return a form with the FormComtrol compknent to wrap around the radio buttons.

RadioGroup have the radio button groups.

FormControlLabel gave the label with the radio button inside.

When we click the button, the handeSubmit function is run.

In the function, we call preventDefault to stop the default submission behavior.

Then we check if the user picked a valid choice.

We set the helper text and the error state so that we can pass that to the error prop.

The helper text is displayed between the radio buttons and the check answer button.

Select

We can add the Select component to add a select dropdown.

For instance, we can write:

import React from "react";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";

export default function App() {
  const [fruit, setFruit] = React.useState("");

  const handleChange = event => {
    setFruit(event.target.value);
  };

  return (
    <form>
      <FormControl>
        <InputLabel id="fruit-label">fruit</InputLabel>
        <Select
          labelId="fruit-label"
          id="fruit"
          value={fruit}
          onChange={handleChange}
        >
          <MenuItem value="apple">Apple</MenuItem>
          <MenuItem value="orange">Orange</MenuItem>
          <MenuItem value="grape">Grape</MenuItem>
        </Select>
      </FormControl>
    </form>
  );
}

to add a dropdown along with a label.

InputLabel lets us add a label for the dropdown.

Select lets us add a dropdown.

labelId of Select should match with the id of the InputLabel .

Native Select

To make the select dropdown display as a native dropdown, we can use the native prop on the Select .

For example, we can write:

import React from "react";
import InputLabel from "@material-ui/core/InputLabel";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";

export default function App() {
  const [fruit, setFruit] = React.useState("");

  const handleChange = event => {
    setFruit(event.target.value);
  };

  return (
    <form>
      <FormControl>
        <Select
          native
          id="fruit"
          value={fruit}
          onChange={handleChange}
        >
          <option value="">Select one</option>
          <option value="apple">Apple</option>
          <option value="orange">Orange</option>
          <option value="grape">Grape</option>
        </Select>
      </FormControl>
    </form>
  );
}

We add the native prop to the Select .

And we replaced the MenuItem with the option element.

We also removed the label, so that it won’t overlap with the dropdown.

Slider

We can add a slider to add a numeric input that’s set by dragging a slider.

To add one, we can use the Slider component.

For instance, we can write:

import React from "react";
import Slider from "@material-ui/core/Slider";

export default function App() {
  const [value, setValue] = React.useState(10);

  const handleChange = event => {
    setValue(event.target.value);
  };

  return (
    <form>
      <Slider
        value={value}
        onChange={handleChange}
      />
    </form>
  );
}

to add a numerical slider.

We have the value state which we set as the value prop.

Also, we have the onChange prop set to our handleChange function.

We call setValue with the slider’s selected value to update the value state.

Now our slider’s handle can be dragged to change its selected value.

Conclusion

We can add a slider by using the Slider component.

Also, we can show errors with radio buttons.

Dropdowns can be added with the Select component.