Nested attributes with Reactjs
Xin chào các bạn. Hôm nay mình xin chia sẻ với các bạn cách sử dụng nested attributes với react mà mình biết. Chắc hẳn khi làm việc với rails các bạn cũng làm với nested attributes sử dụng form for. Form_for đã xây dựng sẵn params truyền lên controller cho các bạn. Tuy nhiên với Reactjs thì sao ...
Xin chào các bạn. Hôm nay mình xin chia sẻ với các bạn cách sử dụng nested attributes với react mà mình biết.
Chắc hẳn khi làm việc với rails các bạn cũng làm với nested attributes sử dụng form for. Form_for đã xây dựng sẵn params truyền lên controller cho các bạn. Tuy nhiên với Reactjs thì sao khi không có form_for cho các bạn sử dụng??? Với bài này hi vọng các bạn hiểu hơn về cách truyền params lên khi sử dụng nested attribute!!!
Question có nhiều answer. Khi tạo Question thì mình tạo answer sử dụng nested_attributes.
Tạo project
cd work_space # Vào thư mục work_space rails new my_app_nested_attributes cd my_app_nested_attributes bundle
Tạo model
rails g model Question title:string rails g model Answer title:string question_id:integer is_correct:boolean
- Ta có question 1-n answer
- Add nested_attributes vào trong model question
class Question < ApplicationRecord has_many :answers, dependent: :destroy accepts_nested_attributes_for :answers, allow_destroy: true end
- Association trong model Answer
class Answer < ApplicationRecord belongs_to :question end
Tạo controller để create question
rails g controller Questions --skip-assets
class QuestionsController < ApplicationController def create @question = Question.new question_params if @question.save render json: {message: "Create success", question: @question}, status: :ok else render json: {mesage: "Create fail", error: @question.errors}, status: :500 end end private def question_params params.require(:question).permit :title, answers_attributes: [:id, :title, :is_correct, :_destroy] end end
Tạo routes
#config/routes.rb resources :question, only: :create
- Tới đây bạn phải có 1 app react rồi thì ms thực hiện được
- Chúng ta sử dụng axios để gửi request từ client lên server
- Sử dụng FormData để lưu dữ liệu
#form question import React from 'react'; import axios from 'axios'; import ReactOnRails from 'react-on-rails'; export default class FormQuestion extends React.Component { constructor(props) { super(props); this.state = { title: ' ', answer_detail: { title: ' ', is_correct: ' ' }, answers: [ ] } } render() { return( <form onSubmit={this.handleSubmitCreateQuestion.bind(this)}> <div className='form-group'> <input type='text' placeholder='title' value={this.state.title} className='form-control' name='title' onChange={this.handleChange.bind(this)} /> </div> <button className='btn btn-success' type='submit'>Create</button> </form> <form> <div className='form-group'> <input type='text' placeholder='title' value={this.state.answer_detail.title} className='form-control' name='title' onChange={this.handleChangeAnswer.bind(this)} /> </div> <div className='form-group'> <input type='text' placeholder='title' value={this.state.answer_detail.is_correct} className='form-control' name='title' onChange={this.handleChangeAnswer.bind(this)} /> </div> <button className='btn btn-success' onClick={this.handleAddAnswer.bind(this)}> Add answer </button> </form> ); } // Thay đổi input form answers handleChangeAnswer(e) { let attribute = event.target.name; Object.assign(this.state.answer_detail, {[attribute]: event.target.value}); this.setState({ answer_detail: this.state.answer_detail }); } // Thay đổi input form question handleChange(e) { let attribute = event.target.name; Object.assign(this.state.title, {[attribute]: event.target.value}); this.setState({ title: this.state.title }); } //Add answer vào mảng answers handleAddAnswer(e) { e.prevenDefault(); this.state.answers.push(this.state.answer_detail); this.setState({ answers: this.state.answers, anser_detail: { title: ' ', is_correct: ' ' } }) } //gửi len sever handleSubmitCreateQuestion(e) { e.preventDefault(); let formData = new FormData(); formData.append('question[title]', this.state.title); //Đoạn code dưới này đây là đế xử lý params truyền lên controller this.state.answers.map((answer_detail, index) => { formData.append('question[answers_attributes]['+ index +'][title]', answer_detail.title ); formData.append('question[answers_attributes]['+ index +'][is_correct]', answer_detail.is_correct ); } formData.append('authenticity_token', ReactOnRails.authenticityToken()); //Token with react-on-rails sinh ra. axios({ url: 'https://localhost:3000/questions, method: 'POST', data: formData }) .then(response => { alert('success'); }) .catch(error => { console.log(error); }); } }
Trên đây là cách mà sử dụng nested_attribute với view tachs biệt rails. Bài viết có gì sai sót mong mọi người góp ý.
Note*: Quan trọng các ban có thể add được params vào request lên controller là oke. Các bạn byebug vào controller để xem params nhé. rất hay đó.
Gợi ý*: Các bạn có thể sử dụng create reactjs với webpack react-on-rails để tạo một ứng dụng sử dụng react trong rails https://github.com/shakacode/react-webpack-rails-tutorial