본문 바로가기
FrontEnd/React

AppBar의 검색기능 구현

by oncerun 2020. 7. 16.
반응형

검색창에 대한 속성을 지정해줍니다.

 <InputBase
              placeholder="검색하기"
              classes={{
                root: classes.inputRoot,
                input: classes.inputInput,
              }}
              inputProps={{ 'aria-label': 'search' }}
              name="searchKeyword"
              value={this.state.searchKeyword}
              onChange={this.handleValueChange}
            />

searchKeyword라는 값으로 state값을 변경할 때마다 고객 정보를 업데이트합니다.

 

그러기 위해서 생성자에서 초기화를 해주어야 합니다. 빈 공백 문자는 모든 문자열이 포함하고 있기에 초기값으로 적당합니다.

  constructor(props) {

    super(props);
      
    this.state = {
  
      customers: '',
      completed : 0,
      searchKeyword : ''
    }
  }

 

onChange이벤트를 받는 handleValueChange를 정의해줍니다.

 

handleValueChange = (e) =>{

  let nextState ={};

  nextState[e.target.name] = e.target.value;
  this.setState(nextState);
  

} 

 

이제 TableBody부분에서 검색된 결과를 필터링해서 보여주기위해 함수를 직접적으로 사용합니다.

 <TableBody>
          {this.state.customers ? 
          this.filteredComponents(this.state.customers) :
             <TableRow>
             <TableCell colSpan="6" align="center">
               <CircularProgress className={classes.progress} variant="determinate" value={this.state.completed}/>
             </TableCell>
           </TableRow>
            }

 

이제 filterComponents함수를 정의합니다.

filteredComponents = (data) => {
  console.log(data);
  data = data.filter((c) => {

    return c.name.indexOf(this.state.searchKeyword) > -1;
  });

 return data.map( (c) => {
    return <Customer stateRefresh={this.stateRefresh} key={c.id} id={c.id} image={c.image} name={c.name} birthday={c.birthday} gender={c.gender} job={c.jon}></Customer>;
  });

import React, { Component } from 'react';
import Customer from './compnents/Customer'
import CustomerAdd from './compnents/CustomerAdd'
import './App.css';
import Paper from  '@material-ui/core/Paper';
import Table from  '@material-ui/core/Table';
import TableHead from  '@material-ui/core/TableHead';
import TableBody from  '@material-ui/core/TableBody';
import TableRow from '@material-ui/core/TableRow';
import TableCell from '@material-ui/core/TableCell';
import CircularProgress from '@material-ui/core/CircularProgress';
import { withStyles } from '@material-ui/core/styles';


import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import InputBase from '@material-ui/core/InputBase';
import { fade } from '@material-ui/core/styles';
import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';


const styles = theme => ({

  root : {
    width : '100%',
    marginTop : theme.spacing(3),
    flexGrow: 1,
    overflowX : "auto"
  },
  table :{

    minWidth : 1080

  },
  TableHead : {

    fontSize: '1.0rem'

  },
  paper : {

    margin : 18

  },


  menu : {

    marginTop : 15,
    marginBottom : 15,
    display : 'flex',
    justifyContent : 'center'

  },
  progress : {

    margin : theme.spacing(2)

  },
  menuButton: {
    marginRight: theme.spacing(2),
  },
  title: {
    flexGrow: 1,
    display: 'none',
    [theme.breakpoints.up('sm')]: {
      display: 'block',
    },
  },
  search: {
    position: 'relative',
    borderRadius: theme.shape.borderRadius,
    backgroundColor: fade(theme.palette.common.white, 0.15),
    '&:hover': {
      backgroundColor: fade(theme.palette.common.white, 0.25),
    },
    marginLeft: 0,
    width: '100%',
    [theme.breakpoints.up('sm')]: {
      marginLeft: theme.spacing(1),
      width: 'auto',
    },
  },
  searchIcon: {
    padding: theme.spacing(0, 2),
    height: '100%',
    position: 'absolute',
    pointerEvents: 'none',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
  },
  inputRoot: {
    color: 'inherit',
  },
  inputInput: {
    padding: theme.spacing(1, 1, 1, 0),
    // vertical padding + font size from searchIcon
    paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,
    transition: theme.transitions.create('width'),
    width: '100%',
    [theme.breakpoints.up('sm')]: {
      width: '12ch',
      '&:focus': {
        width: '20ch',
      },
    },
  },
})


class  App extends React.Component {

  constructor(props) {

    super(props);
      
    this.state = {
  
      customers: '',
      completed : 0,
      searchKeyword : ''
    }
  }

progress = () => {

const {completed} = this.state;
this.setState({ completed : completed >=  100 ? 0 : completed + 1 });

}

handleValueChange = (e) =>{

  let nextState ={};

  nextState[e.target.name] = e.target.value;
  this.setState(nextState);
  

} 

stateRefresh = () => {

  this.setState({

    customers: '',
    completed : 0,
    searchKeyword : ''

  });

  this.callApi()
  .then(res => this.setState({customers : res}))
  .catch(err => console.log(err))

}


componentDidMount() {
  this.timer = setInterval(this.progress, 20);

  this.callApi()
  .then(res => this.setState({customers : res}))
  .catch(err => console.log(err))
  
}

componentWillUnmount() {
 
  clearInterval(this.timer);

}

callApi = async () => {

  const response = await fetch('/api/customers');
  const body = await response.json();
  return body;
}

filteredComponents = (data) => {
  console.log(data);
  data = data.filter((c) => {

    return c.name.indexOf(this.state.searchKeyword) > -1;
  });

 return data.map( (c) => {
    return <Customer stateRefresh={this.stateRefresh} key={c.id} id={c.id} image={c.image} name={c.name} birthday={c.birthday} gender={c.gender} job={c.jon}></Customer>;
  });

}

  render(){

    
    const {classes} = this.props;
    const ceilList = ["번호","이미지","이름","생년월일","성별","직업","설정"];
      return (
        <div className={classes.root}>
           <AppBar position="static">
          
        <Toolbar>
          <IconButton
            edge="start"
            className={classes.menuButton}
            color="inherit"
            aria-label="open drawer"
          >
            <MenuIcon />
          </IconButton>
          <Typography className={classes.title} variant="h6" noWrap>
           고객 관리 시스템
          </Typography>
          <div className={classes.search}>
            <div className={classes.searchIcon}>
              <SearchIcon />
            </div>
            <InputBase
              placeholder="검색하기"
              classes={{
                root: classes.inputRoot,
                input: classes.inputInput,
              }}
              inputProps={{ 'aria-label': 'search' }}
              name="searchKeyword"
              value={this.state.searchKeyword}
              onChange={this.handleValueChange}
            />
          </div>
        </Toolbar>
      </AppBar>
      <div className={classes.menu}>
           <CustomerAdd stateRefresh={this.stateRefresh}/>
           </div>
        <Paper className={classes.paper}>
          <Table className={classes.table}>
            <TableHead>
              <TableRow>
              {ceilList.map(c => {
              return <TableCell className={classes.TableHead}>{c}</TableCell>
              })}
              </TableRow>
            </TableHead>
            <TableBody>
          {this.state.customers ? 
          this.filteredComponents(this.state.customers) :
             <TableRow>
             <TableCell colSpan="6" align="center">
               <CircularProgress className={classes.progress} variant="determinate" value={this.state.completed}/>
             </TableCell>
           </TableRow>
            }
            </TableBody>
          </Table>
        </Paper>
        
        </div>
            );
          }
}
export default withStyles(styles)(App);
반응형

'FrontEnd > React' 카테고리의 다른 글

babel preset env , plugins  (0) 2020.07.16
webpack  (0) 2020.07.16
AppBar 와 웹 폰트 적용  (0) 2020.07.16
삭제기능 추가  (0) 2020.07.13
부모 state변경을통한 갱신  (0) 2020.07.13

댓글