CRUD với react và ruby on rails - Phần 3
Xóa dữ liệu Để xóa dữ liệu, việc đầu tiên chúng ta cần là thêm một nút chức năng để xử lý việc xóa Item trong component <Allitems/> // app/assets/javascripts/components/_all_items.js.jsx var AllItems = React.createClass({ handleDelete() { console.log("delete item clicked"); }, ...
Xóa dữ liệu
Để xóa dữ liệu, việc đầu tiên chúng ta cần là thêm một nút chức năng để xử lý việc xóa Item trong component <Allitems/>
// app/assets/javascripts/components/_all_items.js.jsx var AllItems = React.createClass({ handleDelete() { console.log("delete item clicked"); }, render() { var items = this.props.items.map(item => { return ( <div key={item.id}> <h3>{item.name}</h3> <p>{item.description}</p> <button onClick={this.handleDelete}>Delete</button> </div> ); }); return <div>{items}</div>; } });
Tiếp theo chúng ta cần phải viết thêm một hàm để xử lý việc nhấn xóa
// app/assets/javascripts/components/_body.js.jsx handleDelete() { console.log('in handle delete'); }, render() { return ( <div> <NewItem handleSubmit={this.handleSubmit}/> <AllItems items={this.state.items} handleDelete={this.handleDelete}/> </div> ) } });
Bây giờ chúng ta sẽ sử dụng hàm handleDelete trong component <Allitems/> bằng cách sử dụng props
// app/assets/javascripts/components/_all_items.js.jsx var AllItems = React.createClass({ handleDelete() { this.props.handleDelete(); }, render() { //the rest of the component
Ok. Bây giờ làm thế nào để chúng ta biết được chúng ta đang muốn xóa Item nào? Ở đây chúng ta sẽ sử dụng method bind(). Method bind() sẽ lấy được id của Item this và gửi id dưới dạng tham số.
// app/assets/javascripts/components/_all_items.js.jsx handleDelete(id) { this.props.handleDelete(id); }, render() { var items= this.props.items.map((item) => { return ( <div key={item.id}> <h3>{item.name}</h3> <p>{item.description}</p> <button onClick={this.handleDelete.bind(this, item.id)} >Delete</button> </div> ) });
Tiếp theo chúng ta sẽ thực hiện một Ajax để xóa Item từ database
// app/assets/javascripts/components/_body.js.jsx handleDelete(id) { $.ajax({ url: `/api/v1/items/${id}`, type: 'DELETE', success(response) { console.log('successfully removed item') } }); },
Sau khi thực hiện xong việc xóa dữ liệu chúng ta cần phải tải lại trang danh sách để xem dữ liệu đã xóa hay chưa. Chúng ta sẽ làm điều này bằng cách cập nhật lại mảng items.
// app/assets/javascripts/components/_body.js.jsx handleDelete(id) { $.ajax({ url: `/api/v1/items/${id}`, type: 'DELETE', success:() => { this.removeItemClient(id); } }); }, removeItemClient(id) { var newItems = this.state.items.filter((item) => { return item.id != id; }); this.setState({ items: newItems }); },
Như vậy là chúng ta đã hoàn thành xong việc xóa dữ liệu. Tiếp theo chúng ta cùng nhau xây dựng chức năng sửa dữ liệu.
Sửa dữ liệu
Tất nhiên để có thể chỉnh sửa dữ liệu chúng ta cũng cần thêm một button sửa khi dữ liệu thay đổi và click vào button chúng ta sẽ thực hiện một yêu cầu Ajax nếu thành công Item sẽ được lưu với các giá trị mới. Trước tiên, chúng ta sẽ triển khai button chỉnh sửa và trình xử lý sự kiện.
// app/assets/javascripts/components/_all_items.js.jsx handleEdit() { }, //render() and the rest of the tempalte <button onClick={this.handleEdit()}> Edit </button>
Tiếp theo chúng ta cần thêm một thuộc tính là handleEdit cho Item
// app/assets/javascripts/components/_all_items.js.jsx render() { var items= this.props.items.map((item) => { return ( <div key={item.id}> <Item item={item} handleDelete={this.handleDelete.bind(this, item.id)} handleEdit={this.handleEdit}/> </div> ) });
Bây giờ chúng ta sẽ sửa code ở component Item như sau:
// app/assets/javascripts/components/_item.js.jsx var Item = React.createClass({ render() { return ( <div> <h3>{this.props.item.name}</h3> <p>{this.props.item.description}</p> <button onClick={this.props.handleDelete}>Delete</button> <button onClick={this.props.handleEdit}> Edit </button> </div> ); } });
Tiếp theo chúng ta sẽ di chuyển handleEdit() sang component Item. Chúng ta sẽ có một biến Boolean mà giá trị sẽ được thay đổi bằng cách nhấp nút. Nếu biến đó có giá trị là true thì thuộc tính của item đó sẽ được chuyển thành input và ngược lại. Khi di chuyển handleEdit() sang component Item chúng ta cũng phải sửa lại thuộc tính của nút sửa từ this.props.handleEdit thành this.handleEdit.
// _app/assets/javascripts/components/_item.js.jsx <button onClick={this.handleEdit}> Edit </button>
Và khởi tạo phương thức handleEdit() trong component
// app/assets/javascripts/components/_item.js.jsx var Item = React.createClass({ handleEdit() { console.log('edit button clicked') },
Bây giờ chúng ta sẽ tạo một biến có tên là editable có giá trị ban đầu là false và thiết lập lại là true nếu nút edit được ấn:
// app/assets/javascripts/components/_item.js.jsx var Item = React.createClass({ getInitialState() { return {editable: false} }, handleEdit() { this.setState({editable: !this.state.editable}) }, render() {
Tiếp đến chúng ta cần chỉnh sửa lại render Item để khi click vào nút edit các thuộc tính trong row sẽ được thay đổi thành input
// app/assets/javascripts/components/_item.js.jsx render() { var name = this.state.editable ? <input type='text' defaultValue={this.props.item.name} /> : <h3>{this.props.item.name}</h3>; var description = this.state.editable ? <input type='text' defaultValue={this.props.item.description} />: <p>{this.props.item.description}</p>; return ( <div> {name} {description} <button onClick={this.props.handleDelete} >Delete</button> <button onClick={this.handleEdit}> Edit </button> …
Như vậy, bây giờ name và description sẽ được thay đổi khi this.state.editable được thay đổi. Và hãy làm tương tự với button edit:
// app/assets/javascripts/components/_item.js.jsx <button onClick={this.handleEdit}> {" "} {this.state.editable ? "Submit" : "Edit"}{" "} </button>
Khi các thuộc tính trong row được chuyển thành input chúng ta cần phải đưa giá trị của row vào trong input đó. Để làm được điều này chúng ta làm như sau:
// app/assets/javascripts/components/_item.js.jsx render() { var name = this.state.editable ? <input type='text' ref='name' defaultValue={this.props.item.name} /> : <h3>{this.props.item.name}</h3>; var description = this.state.editable ? <input type='text' ref='description' defaultValue={this.props.item.description} />: <p>{this.props.item.description}</p>;
// app/assets/javascripts/components/_item.js.jsx handleEdit() { if(this.state.editable) { var name = this.refs.name.value; var description = this.refs.description.value; console.log('in handleEdit', this.state.editable, name, description); } this.setState({ editable: !this.state.editable }) },
Bây giờ khi bấm vào sửa chúng ta cần phải gửi nó đến component Body điều này có nghĩa là chúng ta cần phải sử dụng method props để truyền dữ liệu lên. Để làm được điều này chúng ta sẽ bắt đầu trên component Item:
// app/assets/javascripts/components/_item.js.jsx handleEdit() { if(this.state.editable) { var name = this.refs.name.value; var id = this.props.item.id; var description = this.refs.description.value; var item = {id: id , name: name , description: description}; this.props.handleUpdate(item); } this.setState({ editable: !this.state.editable }) },
Trong component Allitem chúng ta sẽ thêm một method handleUpdate sẽ lấy các thuộc tính được thiết lập trong onUpdate:
// app/assets/javascripts/components/_all_items.js.jsx onUpdate(item) { this.props.onUpdate(item); }, render() { var items= this.props.items.map((item) => { return ( <div key={item.id}> <Item item={item} handleDelete={this.handleDelete.bind(this, item.id)} handleUpdate={this.onUpdate}/> </div> ) });
Cuối cùng ở component Body sẽ lấy onUpdate với Item trong đó:
// app/assets/javascripts/components/_body.js.jsx // app/assets/javascripts/components/_body.js.jsx handleUpdate(item) { $.ajax({ url: `/api/v1/items/${item.id}`, type: 'PUT', data: { item: item }, success: () => { this.updateItems(item); } } )}, updateItems(item) { var items = this.state.items.filter((i) => { return i.id != item.id }); items.push(item); this.setState({items: items }); }, render() { return ( <div> <NewItem handleSubmit={this.handleSubmit}/> <AllItems items={this.state.items} handleDelete={this.handleDelete} onUpdate={this.handleUpdate}/> </div> ) } )},
Kết luận:
Như vậy hôm nay mình cũng đã hoàn tất việc xây dựng một ứng dụng nhỏ sử dụng ruby on rails và react. Trong 3 phần trên do kiến thức còn yếu kém nên có thể chưa đúng mong các bạn thông cảm (bow)
Tài liệu: https://www.pluralsight.com/guides/building-a-crud-interface-with-react-and-ruby-on-rails
Github: https://github.com/DangDinhLuan/react-rails