Js 게시판 검색 기능 - Js gesipan geomsaeg gineung

● 기능

▶ 메인화면에 검색기능 추가

▶ 제목검색, 작성자검색 가능하고 키워드를 포함하는 게시물 모두 불러옴

▶ 게시글 클릭시 해당 게시글 페이지로 이동

▶ 검색결과가 총 몇개인지 표시

▶ 게시판 페이지에서 구현했었던 10개씩 불러오는 기능은 구현하지 않음 ( 한 페이지에 모두 나타남 )

● 결과

Js 게시판 검색 기능 - Js gesipan geomsaeg gineung
검색기능이 추가된 메인화면
Js 게시판 검색 기능 - Js gesipan geomsaeg gineung
제목/작성자 선택 후 검색
Js 게시판 검색 기능 - Js gesipan geomsaeg gineung
검색결과 표시화면
Js 게시판 검색 기능 - Js gesipan geomsaeg gineung
게시글 클릭시 해당 게시글 페이지로 이동

● Front -> Main.vue <template>부분 추가코드

<v-row :style="{marginTop: '50px'}">
	<v-col cols="12" md="2" />
	<v-col cols="12" md="2">
    	<v-select
      		:items="searchoption"
      		v-model="searchoptionselected"
      		:style="{width:'90px', marginLeft:'90px'}" />
	</v-col>
	<v-col cols="12" md="4">
		<v-text-field v-model="searchkeyword" dense outlined label="검색키워드" 
		full-width :style="{marginTop:'10px'}"/>
	</v-col>
	<v-col cols="12" md="1">
		<v-btn @click="searchstart" :style="{marginTop:'10px'}">검색</v-btn>
	</v-col>
	<v-col cols="12" md="3" />
</v-row>
<v-row v-if="searchfinish===true" :style="{marginTop:'0px'}">
	<v-col cols="12" md="5"/>
	<v-col cols="12" md="2">
    	<div style="font-size: x-large">검색결과 : {{searchcnt}} 개</div>
    </v-col>
    <v-col cols="12" md="5"/>
</v-row>
<!-- 여기서부터는 게시판 페이지와 거의 일치, 검색완료시에만 표가 나타나게 했고, 게시판 번호 표시 -->
<v-row v-if="searchfinish===true">
	<v-simple-table style="width: 100%;">
		<thead>
			<tr style="font-weight: bolder;">
				<td style="width:10%; font-size: x-large;">게시판</td>
				<td style="width:20%; font-size: x-large;">작성자</td>
				<td style="width:50%; font-size: x-large;">제목</td>
				<td style="width:20%; font-size: x-large;">작성일</td>
			</tr>
		</thead>
		<tbody>
			<tr v-for="item in contentlist" :key="item.id" @click="movetocontent(item.boardnum, item.id)">
				<td>{{item.boardnum}}</td>
				<td>{{item.writer}}</td>
				<td>{{item.title}}</td>
				<td>{{item.createdAt.split('T')[0]}}</td>
			</tr>
		</tbody>
	</v-simple-table>
</v-row>

원래 있던 3개의 버튼 밑에 추가 

<v-footer min-height="50px" color="white"/>

검색된 게시물이 많아 스크롤이 생겼을 때, 가장 아래부분에 빈칸이 없어져서 <v-main/> 다음에 v-footer을 추가

● Front -> Main.vue <script>부분 추가코드

import axios from 'axios'

메인화면에서도 게시글 불러오려면 axios 필요

// data 속성 전체 코드
data() {
    return {
      searchkeyword: '',			// 검색키워드
      searchfinish: false,		// 검색완료시 true로 바뀌고, 이때부터 표 생성
      searchoption: ['제목','작성자'],	// 검색옵션
      searchoptionselected: '제목',	// 검색옵션값 받아오기, 기본값은 제목으로 지정
      searchcnt: 0,			// 검색된 게시글 갯수
      contentlist: [],			// 게시글 리스트
    }
  },
// method 속성 추가 코드
movetocontent(boardnum, id) {	// 검색된 게시글 클릭시 해당 게시글로 이동
	window.location.href = 'http://127.0.0.1:8080/board/' + boardnum + '/content?id=' + id
},
searchstart(){			// 검색버튼 눌렀을때 실행
	if(this.searchkeyword == '') {
		alert('키워드가 없습니다!');
	} else {
		axios({
        	url: "http://127.0.0.1:52273/content/search/",
          	method: "POST",
          	data: {		// 선택된 검색옵션과 검색키워드 넘겨줌
            	searchoption: this.searchoptionselected,
            	searchkeyword: this.searchkeyword,
          	},
        }).then(res => {
        	this.contentlist = res.data;
        	this.searchcnt = this.contentlist[Object.keys(this.contentlist).length-1].cnt;
        	this.contentlist.pop();
        	alert('검색완료!');
        	this.searchfinish = true;
        	this.searchkeyword = '';
        }).catch(err => {
          alert(err);
        });
      }
    },

● Back -> routes/content.js 추가코드

var Op = require('sequelize').Op;

Sequelize에서 특정단어를 포함하는 검색기능 사용할 때 sequelize.Op 필요

router.post('/search', function(req, res){
    if(req.body.searchoption == '제목'){	// searchoption이 '제목'일 때
        db.content.findAndCountAll({
            where: {
                title: {
                    [Op.like]: "%"+req.body.searchkeyword+"%"
                    // "%" + [단어] + "%"를 통해 [단어]가 포함된 모든것 검색 가능
                },
            },
            order: [['id', 'ASC']],
            raw: true,
        }).then(result => {
            var cnt = new Object();
            cnt.cnt = result.count;
            result.rows.push(cnt);
            console.log(result.rows);
            return res.status(200).json(result.rows);
        }).catch(err => {
            console.log(err);
            return res.status(404).json({message: '에러뜸'});
        })
    } else {	// searchoption이 '작성자'일 때
        db.content.findAndCountAll({
            where: {
                writer: {
                    [Op.like]: "%"+req.body.searchkeyword+"%"
                },
            },
            order: [['id', 'ASC']],
            raw: true,
        }).then(result => {
            var cnt = new Object();
            cnt.cnt = result.count;
            result.rows.push(cnt);
            console.log(result.rows);
            return res.status(200).json(result.rows);
        }).catch(err => {
            console.log(err);
            return res.status(404).json({message: '에러뜸'});
        })
    }
});