iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 20
0
Modern Web

RRRR的世界 (Ruby on Rails + React + Redux)系列 第 20

Day 20, Reading List - React部分-2

先上圖,不囉嗦。
http://ithelp.ithome.com.tw/upload/images/20170105/20103835DdbC7uF1GB.png

這邊還只有UI的功能而已,補上三支code!

ReadingListWidget 準備要專門與後端溝通!

還有包裝component進去。

import React, { PropTypes } from 'react';
import Book from './Book';
import BookInputWidget from './BookInputWidget';
const  propTypes = {
  updateBooks: PropTypes.func.isRequired,
  books: PropTypes.array.isRequired,
};
class ReadingListWidget extends React.Component {
  constructor(props){
    super(props);
		this.onBookDelete = this.onBookDelete.bind(this)
		this.onBookModify = this.onBookModify.bind(this)
		this.onConfirmModify = this.onConfirmModify.bind(this)
		this.onCancelModify = this.onCancelModify.bind(this)
		this.state = {
			books: props.books,
			modifyList: []
		}
  }

	onBookDelete(id){
		console.log(id);
		let books = this.state.books.filter((book, i) => {
			console.log(book);
			return book.id!=id;
		});
		this.setState({books})
	}
	onBookModify(id){
		console.log(id);
		let modifyList = this.state.modifyList;
		if(modifyList.indexOf(id)==-1){
			modifyList.push(id);
		}
		this.setState({modifyList});
	}
	onCancelModify(id){
		let modifyList = this.state.modifyList.filter((modifiedID) => {
			return modifiedID!=id;
		});
		this.setState({modifyList});
	}
	onConfirmModify(id){
		let modifyList = this.state.modifyList.filter((modifiedID) => {
			return modifiedID!=id;
		});
		this.setState({modifyList});
	}
  render() {
    const { books, modifyList } = this.state;
		const bookComponents = books.map((book, index) => {
			if(modifyList.indexOf(book.id)==-1){
				return(
					<Book { ...book}
								key={index} 
								onDelete = {this.onBookDelete}
								onModify = {this.onBookModify}
					/>
				);
			}else{
				return(
					<BookInputWidget { ...book}
								key={index} 
								onConfirm = {this.onConfirmModify}
								onCancel = {this.onCancelModify}
					/>
				);
			}
		});	
    return (
      <div className="container">
        <h3>
					Reading List
        </h3>
				<div className="row">
					<div className="col-md-1">{''}</div>
					<div className="col-md-2">閱讀狀態</div>
					<div className="col-md-3">書名</div>
					<div className="col-md-2">作者</div>
					<div className="col-md-4">
					</div>
				</div>
				{bookComponents}
        <hr />
					<BookInputWidget />
        <hr />
      </div>
    );
  }
}
ReadingListWidget.propTypes = propTypes;
export default ReadingListWidget;

Books 就沒什麼了 把閱讀清單列出來!

import React, { PropTypes } from 'react';
const propTypes = {
	id:						PropTypes.number.isRequired,
	name:					PropTypes.string.isRequired,
	status:				PropTypes.string.isRequired,
	author_id:		PropTypes.number.isRequired,
	author_name:	PropTypes.string.isRequired,
	onDelete:			PropTypes.func.isRequired,
	onModify:			PropTypes.func.isRequired
}
class Book extends React.Component {
	constructor(props){
		super(props);
		this.onCheckboxChange = this.onCheckboxChange.bind(this);
		this.onModifyClick = this.onModifyClick.bind(this);
		this.onDeleteClick = this.onDeleteClick.bind(this);
		this.state = {
			status: props.status
		}
	}
	onCheckboxChange(e){
		let target = e.target;
		target.indeterminate = true;
		switch(this.state.status){
			case "unread":
				target.checked = false;
				target.indeterminate = true;
				this.setState({status: 'reading'});
				break;
			case "reading":
				target.checked = true;
				target.indeterminate = false;
				this.setState({status: 'finished'});
				break;
			case "finished":
				target.checked = false;
				target.indeterminate = false;
				this.setState({status: 'unread'});
				break;
		}
	}
	onDeleteClick(e){
		let {id, onDelete} = this.props;
		onDelete(id);
	}
	onModifyClick(e){
		let {id, onModify} = this.props;
		onModify(id);
	}
	render() {
		const {id, name,  author_name} = this.props;
		const {status} = this.state;
		return (
			<div className="row">
				<div className="col-md-1">{id}</div>
				<div className="col-md-2">
					<input type="checkbox" name={"status"} onChange={this.onCheckboxChange} />
					<label>{status}</label>
				</div>
				<div className="col-md-3">{name}</div>
				<div className="col-md-2">{author_name}</div>
				<div className="col-md-4">
					<button type="button" className="btn btn-outline-success" onClick={this.onModifyClick}>Modify</button>
					<button type="button" className="btn btn-outline-danger" onClick={this.onDeleteClick}>Delete</button>
				</div>
			</div>
		);
	}
}
Book.propTypes = propTypes;
export default Book;

BookInputWidget這支是新的! 接收input然後回傳給server!

import React, { PropTypes } from 'react';
const propTypes = {
	id:						PropTypes.number,
	name:					PropTypes.string,
	status:				PropTypes.string,
	author_id:		PropTypes.number,
	author_name:	PropTypes.string,
	onCreate:			PropTypes.func,
	onCancel:			PropTypes.func,
	onConfirm:		PropTypes.func
}
const defaultProps = {
	id:						0,
	name:					'',
	status:				'unread',
	author_id:		0,
	author_name:	'',
	onCreate:			function(){},
	onCancel:			function(){},
	onConfirm:		function(){}
}
class BookInputWidget extends React.Component {
	constructor(props){
		super(props);
		this.onCheckboxChange = this.onCheckboxChange.bind(this);
		this.onConfirmClick = this.onConfirmClick.bind(this);
		this.onCancelClick = this.onCancelClick.bind(this);
		this.onCreateClick = this.onCreateClick.bind(this);
		console.log(props)
		this.state = {
			name: props.name || '',
			status: props.status || 'unread',
			author_name: props.author_name || ''
		}
	}
	onCheckboxChange(e){
		let target = e.target;
		target.indeterminate = true;
		switch(this.state.status){
			case "unread":
				target.checked = false;
				target.indeterminate = true;
				this.setState({status: 'reading'});
				break;
			case "reading":
				target.checked = true;
				target.indeterminate = false;
				this.setState({status: 'finished'});
				break;
			case "finished":
				target.checked = false;
				target.indeterminate = false;
				this.setState({status: 'unread'});
				break;
		}
	}
	onCreateClick(e){
		let {id, onCreate} = this.props;
		onCreate(id);
	}
	onCancelClick(e){
		let {id, onCancel} = this.props;
		onCancel(id);
	}
	onConfirmClick(e){
		let {id, onConfirm} = this.props;
		onConfirm(id);
	}
	render() {
		const {id} = this.props;
		const {name, status, author_name} = this.state;
		let buttons=null
		if(id==0){
			buttons=<span className="create-book">
					<button type="button" className="btn btn-primary" onClick={this.onCreateClick}>Create</button>
				</span>
		}else{
			buttons=<span className="create-book">
					<button type="button" className="btn btn-success" onClick={this.onConfirmClick}>Confirm</button>
					<button type="button" className="btn btn-secondary" onClick={this.onCancelClick}>Cancel</button>
				</span>
		}
		return (
			<div className="row">
				<div className="col-md-1">{''}</div>
				<div className="col-md-2">
					<input type="checkbox" name={"status"} onChange={this.onCheckboxChange} />
					<label>{status}</label>
				</div>
				<div className="col-md-3">
					<input type="text" name="name" value={name}/>
				</div>
				<div className="col-md-2"><input type="text" name="author_name" value={author_name} /></div>
				<div className="col-md-4">
					{buttons}
				</div>
			</div>
		);
	}
}
BookInputWidget.propTypes = propTypes;
BookInputWidget.defaultProps = defaultProps;
export default BookInputWidget;

如此一來分工就滿清楚的了,ReadingListWidget專門Reload資訊,Book專門show出資訊,然後BookInputWidget負責修改或新增book資訊。

明天要打包JSON,寫AJAX,串接後端rails服務了!!
我會在犧牲掉兩天deploy...如果篇數不夠的話QQ


上一篇
Day 19, Reading List - React部分-1
下一篇
Day 21, Reading List - React部分-3
系列文
RRRR的世界 (Ruby on Rails + React + Redux)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言