Kết hợp Vuejs với Rails

Giới thiệu Vuejs Vue (phát âm là /vjuː/, giống view) là một progressive framework dùng để xây dựng giao diện người dùng ( UI ). Không giống các monolithic framework. Phần thư viện lõi của Vue chỉ tập trung vào lớp view mà thôi, và nó rất dễ để làm quen và tích hợp với các thư viện khác hoặc các project có sẵn. Mặt khác, Vue lại chứa đựng một sức mạnh rất lớn trong việc xây dựng Single-Page Applications khi được kết hợp với công cụ build và các thư viện/component được xây dựng bởi cộng đồng. Các bạn có thể tham khảo tại đây https://vuejs.org/v2/api/ Để cài đặt và sử dụng Tạo một ứng dụng rails

rails new vuejs_demo

kết hợp vuejs vào trong ứng dụng rails chúng ta có nhiều cách, có thể dùng gem hoặc dùng bower Ở đây mình dùng bower file bower.json

{
  "name": "vuejs_demo",
  "version": "0.0.0",
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "vue": "~1.0.17",
    "vue-resource": "~0.7.0"
  }
}

tạo thêm file .bowerrc, sẽ tạo ra đường dẫn để chưa src Vuejs

{
  "directory": "vendor/assets/javascripts"
}

Chúng ta chạy lệnh

bower install

bower sẽ kéo vuejs về trong mục /vendor/assets/javascripts trong file assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require vue
//= require_tree .

Bây giờ chúng ta tạo model cho project, ở đây chúng ta sẽ tạo ra 2 model Teams và Player, Team has_many player, player belongs_to Team , và sử dụng form của vuejs để tạo object thay vì dùng accepts_nested_attributes_for Tạo model Team

rails g model Teams name:string 

Tạo model Player

rails g model Players name:string position:string team:references

Get Vue Up and Running Tạo controller

rails g controller teams 
rails g controller api/v1/teams 

Trong router chúng ta sẽ thay đổi một chút

Rails.application.routes.draw do
  root 'teams#new'
  namespace :api do
    namespace :v1 do
      get '/teams' => 'teams#index'
      post '/teams' => 'teams#create'
    end
  end
end

Chúng ta tạo Vue controller , tạo file teams_ctrl.js

$(document).on('ready', function() {
  new Vue({
    el: '#new-team-form',
    data: {
      message: 'Vue is working!'
    }
  })
})

Trong views/teams chúng ta tạo new.html.erb

<div id="new-team-form">
  {{ message }}
</div>

bây giờ chúng ta run server và sẽ thấy dòng 'Vue is working!'

Ok, bây giờ chúng ta sẽ tạo 1 form tạo mới team, sử dụng vuejs

<div class="container container-margin">
  <div id="new-team-form">
    <div class="form-group">
      <label for="name" class="form-label">Team Name</label>
      <input id="name" v-model="name" class="form-control">
      <p class="validation-error">{{ errors }}</p>
    </div>
    <div v-for="player in players">
      <div class="form-group player-form">
        <label for="name" class="form-label">Player Name</label>
        <input id="name" v-model="player.name" class="form-control">
      </div>
      <div class="form-group player-form">
        <label for="position" class="form-label">Player Position</label>
        <input id="position" v-model="player.position" class="form-control">
      </div>
    </div>
    <div class="form-group add-player-btn">
      <button v-on:click="addPlayer" class="btn btn-info btn-sm">Add Player</button>
    </div>
    <div class="form-group">
      <button v-on:click="saveTeam(name)" class="btn btn-success">Save Team</button>
    </div>
  </div>
</div>

file teams_controller.rb

class Api::V1::TeamsController < ApplicationController

  def create
    binding.pry
    @team = Team.new(name: params[:name])
    players = JSON.parse(params[:players])
    players.each do |player|
      @team.players.new(
        name: player["name"],
        position: player["position"]
      )
    end
    if @team.save
      render 'show.json.jbuilder'
    else
      render json: {errors: @team.errors.full_messages}, status: 422
    end
  end

  def show
    @team = Team.find(params[:id])
  end
end

Tạo file show.json.jbuilder trong pp/views/api/v1/teams

json.(@team, :id, :name)
json.players @team.players, :name, :position

Bây giờ ta sẽ dùng vuejs để tạo params teams trong file team_ctrl.js

$(document).on('ready', function() {
  new Vue({
    el: '#new-team-form',
    data: {
      name: "",
      teams: [],
      players: [],
      errors: []
    },
    methods: {
      saveTeam: function(name) {
        var params = {
          name: name,
          players: JSON.stringify(this.players) // converts params to an array
        };
        $.post('/api/v1/teams.json', params).done(function(result) {
          // console.log(result);
          window.location = "/teams/" + result.id;
        }.bind(this)).fail(function(result) {
            this.errors = result.responseJSON.errors;
        }.bind(this));
      },
      addPlayer: function() {
        this.players.push({
          name: '',
          position: ''![](https://viblo.asia/uploads/c5df6afc-85a1-4e63-92ce-1f79ebbd92cc.png)
        })
      }
    }
  })
})

Chúng ta run server và kiểm tra kết quả

khi chúng ta submit, param được truyền lên controller sẽ như thế này: Và kết quả: