iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
自我挑戰組

Material UI in React系列 第 10

Material UI in React [Day 10] Inputs (Text Field) 文本輸入框

Text Field

TextField 包裝組件是一個完整的表單控件,包括標籤、輸入和幫助文本,它支持標準、輪廓和填充樣式。簡單來說它是一個整合了 FormControl, InputLabel, Input, FormHelperText 的綜合組件,從原生的 html 標籤來看,它確實是使用了 fieldset 來整合整個 input 輸入框的樣式,這也是它會命名為text field的原因吧。
以下兩種寫法是相同的

<TextField id="textfield" label="Standard" />
<FormControl>
<InputLabel htmlFor="form-control">Form Control</InputLabel>
<Input id="form-control" />
</FormControl>

variant

在基礎引入狀態下的 variant 有以下三種,預設值為 standard:

<form noValidate autoComplete="off">
  <TextField id="standard-basic" label="Standard" />
  <TextField id="filled-basic" label="Filled" variant="filled" />
  <TextField id="outlined-basic" label="Outlined" variant="outlined" />
</form>

表單屬性

也支援一些基本的表單屬性,例如:required, disabled, type...等等,也包含了helperText,通常用來描述如何使用這個輸入框。

<TextField
  required
  id="standard-required"
  label="Required"
  defaultValue="Hello World"
/>
<TextField
  disabled
  id="standard-disabled"
  label="Disabled"
  defaultValue="Hello World"
/>
<TextField
  id="standard-password-input"
  label="Password"
  type="password"
  autoComplete="current-password"
/>
<TextField
  id="standard-read-only-input"
  label="Read Only"
  defaultValue="Hello World"
  InputProps={{
    readOnly: true,
  }}
/>
<TextField
  id="standard-number"
  label="Number"
  type="number"
  InputLabelProps={{
    shrink: true,
  }}
/>
<TextField id="standard-search" label="Search field" type="search" />
<TextField
  id="standard-helperText"
  label="Helper text"
  defaultValue="Default Value"
  helperText="Some important text"
/>

error

可以使用 error 來切換錯誤的狀態,同時也可使用 helperText 來給用戶提供錯誤提示訊息。

<TextField
  variant="filled"
  error
  label="Error"
  defaultValue="Hello World"
  helperText="Incorrect entry."
/>

錯誤的部分可以按個人喜好選擇搭配 formik 或是 react-hook-form 來做檢核,之後會做詳細的講解如何與 react-hook-form 做搭配。

multiline

使用 multiline,能將原本的輸入框轉換成多行,類似 textarea 的特性,簡單來說就是 textarea 更換皮膚。

<TextField
  label="Multiline"
  multiline
  maxRows={4}
  value={value}
  onChange={handleChange}
/>
<TextField
  label="Multiline Placeholder"
  variant="filled"
  placeholder="Placeholder"
  multiline
/>
<TextField
  label="Multiline"
  variant="outlined"
  multiline
  rows={4}
  defaultValue="Default Value"
/>

select

使用 select 可以在輸入框内插入一個 Select 組件,不過通常會直接使用 Select 組件來處理:

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

const currencies = [
  {
    value: 'USD',
    label: '$',
  },
  {
    value: 'EUR',
    label: '€',
  },
  {
    value: 'BTC',
    label: '฿',
  },
  {
    value: 'JPY',
    label: '¥',
  },
];

const useStyles = makeStyles((theme) => ({
  root: {
    '& .MuiTextField-root': {
      margin: theme.spacing(1),
      width: '25ch',
    },
  },
}));

export default function MultilineTextFields() {
  const classes = useStyles();
  const [currency, setCurrency] = React.useState('EUR');

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

  return (
    <form className={classes.root} noValidate autoComplete="off">
      <div>
        <TextField
          id="standard-select-currency"
          select
          label="Select"
          value={currency}
          onChange={handleChange}
          helperText="Please select your currency"
        >
          {currencies.map((option) => (
            <MenuItem key={option.value} value={option.value}>
              {option.label}
            </MenuItem>
          ))}
        </TextField>
        <TextField
          id="standard-select-currency-native"
          select
          label="Native select"
          value={currency}
          onChange={handleChange}
          SelectProps={{
            native: true,
          }}
          helperText="Please select your currency"
        >
          {currencies.map((option) => (
            <option key={option.value} value={option.value}>
              {option.label}
            </option>
          ))}
        </TextField>
      </div>
      <div>
        <TextField
          id="filled-select-currency"
          select
          label="Select"
          value={currency}
          onChange={handleChange}
          helperText="Please select your currency"
          variant="filled"
        >
          {currencies.map((option) => (
            <MenuItem key={option.value} value={option.value}>
              {option.label}
            </MenuItem>
          ))}
        </TextField>
        <TextField
          id="filled-select-currency-native"
          select
          label="Native select"
          value={currency}
          onChange={handleChange}
          SelectProps={{
            native: true,
          }}
          helperText="Please select your currency"
          variant="filled"
        >
          {currencies.map((option) => (
            <option key={option.value} value={option.value}>
              {option.label}
            </option>
          ))}
        </TextField>
      </div>
      <div>
        <TextField
          id="outlined-select-currency"
          select
          label="Select"
          value={currency}
          onChange={handleChange}
          helperText="Please select your currency"
          variant="outlined"
        >
          {currencies.map((option) => (
            <MenuItem key={option.value} value={option.value}>
              {option.label}
            </MenuItem>
          ))}
        </TextField>
        <TextField
          id="outlined-select-currency-native"
          select
          label="Native select"
          value={currency}
          onChange={handleChange}
          SelectProps={{
            native: true,
          }}
          helperText="Please select your currency"
          variant="outlined"
        >
          {currencies.map((option) => (
            <option key={option.value} value={option.value}>
              {option.label}
            </option>
          ))}
        </TextField>
      </div>
    </form>
  );
}

InputAdornment

可用於向輸入框添加前綴、後缀或動作。 例如,可以用一個icon或按鈕來隱藏或者顯示輸入框內的密碼範例

<TextField
  label="加入前綴"
  id="standard-start-adornment"
  InputProps={{
    startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
  }}
/>
<TextField
  label="加入後綴"
  id="standard-end-adornment"
  InputProps={{
    startAdornment: <InputAdornment position="end">Kg</InputAdornment>,
  }}
/>

Layout

使用 margin 屬性,你可以改變數入框的垂直間距。 若您使用 none (預設值),將不會在 FormControl 上添加間距,相對的,使用 dense 和 normal 會添加間距。
fullWidth 属性,使用它時,輸入框會占滿整個容器的寬度。

<TextField
  id="outlined-full-width"
  label="Label"
  style={{ margin: 8 }}
  placeholder="Placeholder"
  helperText="Full width!"
  fullWidth
  margin="normal"
  InputLabelProps={{
    shrink: true,
  }}
  variant="outlined"
/>
<TextField
  label="None"
  id="outlined-margin-none"
  defaultValue="Default Value"
  className={classes.textField}
  helperText="Some important text"
  variant="outlined"
/>
<TextField
  label="Dense"
  id="outlined-margin-dense"
  defaultValue="Default Value"
  className={classes.textField}
  helperText="Some important text"
  margin="dense"
  variant="outlined"
/>
<TextField
  label="Normal"
  id="outlined-margin-normal"
  defaultValue="Default Value"
  className={classes.textField}
  helperText="Some important text"
  margin="normal"
  variant="outlined"
/>

shrink

輸入框標籤的 "shrink" 狀態不正確,標籤應在輸入框顯示内容的時候立即收縮。 在某些情況下,我們無法確定輸入框的 "shrink" 狀態(如數字、日期時間)如此便有可能出現重疊。
若要解決此問題,可以在輸入框的標籤上强制給予 "shrink" 狀態。

<TextField InputLabelProps={{ shrink: true }} />

<InputLabel shrink>hello</InputLabel>

至此今天大致講解完基本的應用了,明天會接續講解 date/time picker 日期輸入的部分。


上一篇
Material UI in React [Day9] Inputs (Radio) 單選 & (Switch) 開關
下一篇
Material UI in React [ Day 11] Date & Time picker 日期時間輸入
系列文
Material UI in React30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言