簡體   English   中英

深度嵌套的rails vue.js(屬性的屬性)

[英]rails vue.js deep nested (attributes of attribute)

我通過觀看gorails教程創建了一個嵌套表單,這很好,我做到了。 當我想在其他嵌套模型下創建嵌套模型時,問題開始了。 我有Survey模型,它是主要模型。 然后我添加了Question模型,並使用vue.js制作了表單。 因此我在問題中添加了Choice模型(您可以在測量控制器參數中注意到)第一個問題是; 我不知道如何在vue.js控件中定義/實現。(hello_vue.js)第二個要點是:如何在new.html中創建表單元素

這是我的survey.rb模型:

class Survey < ApplicationRecord
    has_many :questions, dependent: :destroy
    accepts_nested_attributes_for :questions, allow_destroy: true
    belongs_to :user
end

和surveys_controller.rb

class SurveysController < ApplicationController
  before_action :set_survey, only: [:show, :edit, :update, :destroy]


    def survey_params
      params.require(:survey).permit(:user_id, :name, questions_attributes:[:id,:survey_id, :title, :qtype, :_destroy, choices_attributes:[:id,:question, :ctext]])
    end
end

這是Survey的嵌套模型:question.rb:

class Question < ApplicationRecord
    enum qtype: [:multiple_choice, :check_boxes, :short_answer]
  belongs_to :survey
  has_many :choices
  accepts_nested_attributes_for :choices, allow_destroy: true
end

所以最終vue.js文件:

 import TurbolinksAdapter from 'vue-turbolinks'
 import Vue from 'vue/dist/vue.esm'
 import VueResource from 'vue-resource'

Vue.use(VueResource)
Vue.use(TurbolinksAdapter)

Vue.component('app', App)
 document.addEventListener('turbolinks:load', () => {
    Vue.http.headers.common['X-CSRF-Token'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
      var element = document.getElementById("survey-form")


if (element != null){
    var survey = JSON.parse(element.dataset.survey)
    var questions_attributes = JSON.parse(element.dataset.questionsAttributes)
    var choices_attributes = JSON.parse(element.dataset.choicesAttributes)
    questions_attributes.forEach(function(question) { question._destroy = null })
    survey.questions_attributes = questions_attributes

    var app = new Vue({

    el: element,
    //mixins: [TurbolinksAdapter],  
    data: function(){
        return { survey: survey }

    },

    methods:{
        addQuestion: function(){

            this.survey.questions_attributes.push({
                id: null,
                title:"",
                qtype:"",
                _destroy: null


            })
        },
       removeQuestion: function(index) {
          var question = this.survey.questions_attributes[index]

          if (question.id == null) {
            this.survey.questions_attributes.splice(index, 1)
          } else {
            this.survey.questions_attributes[index]._destroy = "1"
          }
        },
        undoRemove: function(index) {
          this.survey.questions_attributes[index]._destroy = null
        },

                saveSurvey: function() {
          // Create a new survey
          if (this.survey.id == null) {
            this.$http.post('/surveys', { survey: this.survey }).then(response => {
              Turbolinks.visit(`/surveys/${response.body.id}`)
            }, response => {
              console.log(response)
            })




          // Edit an existing survey
          } else {
            this.$http.put(`/surveys/${this.survey.id}`, { survey: this.survey }).then(response => {
              Turbolinks.visit(`/surveys/${response.body.id}`)
            }, response => {
              console.log(response)
            })
          }
        },


        existingSurvey: function() {
          return this.survey.id != null
        }

    }   
   })
    }


 })

_form.html.erb

<%= content_tag :div,
    id: "survey-form",
    data: {
      survey: survey.to_json(except: [:created_at, :updated_at]),
      questions_attributes: survey.questions.to_json,

    } do %>

<label>Survey Name</label>
<input qtype="text" v-model="survey.name">

<h4>Questions</h4>
<div v-for="(question, index) in survey.questions_attributes">
    <div v-if="question._destroy == '1'">
      {{ question.title }} will be removed. <button v-on:click="undoRemove(index)">Undo</button>
    </div>
    <div v-else>
      <label>Question</label>

      <input qtype="text" v-model="question.title" />

     <label>Qestion qtype</label>
  <select v-model="question.qtype">
  <option v-for="qtype in <%= Question.qtypes.keys.to_json %>"
    :value=qtype>
    {{ qtype }}
  </option>
</select>


      <button v-on:click="removeQuestion(index)">Remove</button>
    </div>

    <hr />
  </div>

  <button v-on:click="addQuestion">Add Question</button>

<br>

<button v-on:click="saveSurvey" >Save Survey</button>


    <% end %>

我遵循了同一教程,並開始使用帶有更復雜的嵌套屬性的JSON.parse遇到問題。 嘗試使用Jbuilder構建JSON對象,並查看gon gem以將Rails變量傳遞到Javascript中。 使用Rails所需的嵌套命名,查詢數據庫並將結果傳遞到Javascript文件將更加容易。 例如...

survey = @survey

json.id survey.id

json.survey do
  json.(survey, :user_id, :name)  
  json.questions_attributes survey.questions do |question|
    json.(question, :id, :title, :qtype, :_destroy)
    json.choices_attributes question.choices do |choice|
      json.(choice, :id, :ctext)
    end
  end
end

它可以讓你做...

var survey = gon.survey

代替...

var survey = JSON.parse(element.dataset.survey)

您可以從控制器操作中傳遞gon.jbuilder ,並准備好定義的JSON對象並在Vue中可用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM