目次
新人に負けない本棚管理サイト その1(プロローグ)
新人に負けない本棚管理サイト その2(環境構築編)
新人に負けない本棚管理サイト その3(トップページ作成編)
新人に負けない本棚管理サイト その4(データベース検索編①)
新人に負けない本棚管理サイト その5(データベース検索編②)
新人に負けない本棚管理サイト その6(データの削除・登録・更新)
目標
- データベースに問い合わせしてデータを取得する
- 取得したデータを画面に表示する
- 検索できるようにする ←今回はココだけ
- おまけ(MVC化)
おさらい+今回やること
データベース検索編①では、ページロードしたときにデータベースから本情報を全件取得して画面に表示させるところまで作りました。
(本来なら10件程度でペジネーションすべきですが、新人がつくることを想定しているのでそこまでこだわりませんという言い訳)
その中で「データベースの接続」「クエリ実行」「画面へ検索結果バインド」に触れました。
今回は全ての本情報から検索条件に合うものを絞り込み、ヒットしたものだけを画面に表示させます。
イベント定義
検索ボタンを押したときに行う処理を定義し、この中で検索処理をします。
importLayoutfrom'../../components/layout';importReactfrom'react';import{Container,Row,Col,Table,Form}from'react-bootstrap';exportdefaultclassIndexextendsReact.Component{constructor(props){super(props);this.state={booklist:[]};}staticasyncgetInitialProps(){constres=awaitfetch(location.protocol+'//'+location.host+'/bookmanager/get');constallBooks=awaitres.json();return{allBooks};}/* Componentがマウントされたときに呼ばれる */componentDidMount(){// setStateは即時更新ではなく、更新の予約をするだけ(非同期)this.setState({booklist:this.props.allBooks});}// 追記ここからonSearchClick(){// 入力値取得letinputTitle=document.getElementById("txtTitle").value;letinputAuthor=document.getElementById("txtAuthor").value;// すべての本情報constallBooks=this.props.allBooks;// filterconstfltTitle=(item)=>{return(item.title.indexOf(inputTitle)!==-1);};constfltAuthor=(item)=>{return(item.author.indexOf(inputAuthor)!==-1);};constfltBoth=(item)=>{return(item.title.indexOf(inputTitle)!==-1)&&(item.author.indexOf(inputAuthor)!==-1);}// propsから絞り込みif(!inputTitle){if(!inputAuthor){// 両方空欄なら全件取得this.setState({booklist:allBooks});}else{// 著者だけ入力letbooksMatchAuthor=allBooks.filter(fltAuthor);this.setState({booklist:booksMatchAuthor});}}else{if(!inputAuthor){// タイトルだけ入力letbooksMatchTitle=allBooks.filter(fltTitle);this.setState({booklist:booksMatchTitle});}else{// 両方入力letbooksMatchBoth=allBooks.filter(fltBoth);this.setState({booklist:booksMatchBoth});}}}// 追記ここまでrender(){constsearchAreaStyle={padding:"40px 0px"};constbtnSearchStyle={paddingTop:"1.0rem"};constrows=this.state.booklist;consttrlist=[];for(letkeyinrows){trlist.push(<trkey={key}><td>{rows[key]['title']}</td><td>{rows[key]['author']}</td><td>{rows[key]['publisher']}</td><td>{rows[key]['finished_at']}</td></tr>);}return(<div><Layout><divclassName="pageTop"><h1>BookManager</h1><p>書籍名、著者名から検索してください。</p></div><Containerstyle={searchAreaStyle}><Row><Colmd={1}sm={12}><Form.Label>書籍名</Form.Label></Col><Colmd={5}sm={12}><Form.Controlid="txtTitle"type="text"name="title"placeholder="例)PHP Python 入門"autoComplete="new-pasword"/></Col><Colmd={1}sm={12}><Form.Label>著者名</Form.Label></Col><Colmd={5}sm={12}><Form.Controlid="txtAuthor"type="text"name="author"placeholder="ひらがなでもOKです"/></Col></Row><Rowstyle={btnSearchStyle}><Colmd={12}sm={12}className="text-right"><inputclassName="btn btn-primary"type="button"value="検索"autoComplete="new-pasword"onClick={()=>{this.onSearchClick()}}/></Col></Row></Container><ContainerclassName="results"><Row><Tablestripedborderedsize="sm"><thead><tr><th>タイトル</th><th>著者名</th><th>出版社</th><th>読了日</th></tr></thead><tbody>{trlist}</tbody></Table></Row></Container></Layout><stylejsx>{`
.pageTop {
text-align: center;
padding: 40px 0px;
}
`}</style></div>);}}
propsから絞り込んでstateに設定しているだけですね。
検索してみよう!
初期表示
タイトルだけで検索すると
著者だけで検索すると
両方で検索すると
最後に空欄で検索すると
ちゃんと絞り込みできてますね\('ω' )/ヤッター
MVC化(工事中)
ExpressはMVCフレームワークではないので、ModelやControllerに相当するものがありません。
そのためserver.jsの中にリクエストに対する処理を全部書いていますが、今後server.jsがモコモコと膨らみコードの見通しが悪くなっていきます。
今回の内容が少ないので、ついでに疑似的なModel・Controllerを用意してそこに処理を任せように書き換えたい思います。参考サイト
Model
データベース等からデータを取ってきてControllerに返す役割を持ちます。
Controller
リクエストに対する処理をModelへ流す、Modelから受け取った結果をViewに渡す役割を持ちます。
Modelでエラーがあった場合はエラーページに遷移させることもできます。
お疲れ様でした
無事に本を検索することができました。
ここまできたら、同じように「削除」「登録」「変更」の機能を追加するだけです。
登録・更新ではユーザーの入力が伴うため、新しいページをつくります。