rails vue.js 深度嵌套(属性的属性) [英] rails vue.js deep nested (attributes of attribute)

查看:32
本文介绍了rails vue.js 深度嵌套(属性的属性)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过观看 gorails 教程创建了一个嵌套表单,我完成了它.当我想在其他嵌套模型下创建嵌套模型时,问题开始了.我有 Survey 模型,它是主要模型.然后我添加了 Question 模型并使用 vue.js 制作表单.所以我在问题下添加了 Choice 模型(您可以在调查控制器参数中注意到)第一个问题是;我不知道如何在 vue.js 控件中定义/实现.(hello_vue.js) 第二个重要点是:如何在 new.html 中创建表单元素

这是我的survey.rb模型:

班级调查<申请记录has_many :questions, 依赖: :destroyaccepts_nested_attributes_for :questions, allow_destroy: true归属地:用户结尾

和surveys_controller.rb

class SurveysController <应用控制器before_action :set_survey, only: [:show, :edit, :update, :destroy]定义调查参数params.require(:survey).permit(:user_id, :name, questions_attributes:[:id,:survey_id, :title, :qtype, :_destroy, choice_attributes:[:id,:question, :ctext]])结尾结尾

这是调查的嵌套模型:question.rb:

类问题<申请记录枚举 qtype: [:multiple_choice, :check_boxes, :short_answer]归属地:调查has_many :选择accepts_nested_attributes_for :choices, allow_destroy: true结尾

最后是 vue.js 文件:

 从 'vue-turbolinks' 导入 TurbolinksAdapter从 'vue/dist/vue.esm' 导入 Vue从 'vue-resource' 导入 VueResourceVue.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("调查表")如果(元素!= null){var 调查 = JSON.parse(element.dataset.survey)var questions_attributes = JSON.parse(element.dataset.questionsAttributes)var choice_attributes = JSON.parse(element.dataset.choicesAttributes)questions_attributes.forEach(function(question) { question._destroy = null })Survey.questions_attributes = questions_attributesvar app = new Vue({el:元素,//mixins: [TurbolinksAdapter],数据:函数(){返回{调查:调查}},方法:{添加问题:函数(){this.survey.questions_attributes.push({id:空,标题:"",qtype:"",_destroy: 空})},移除问题:函数(索引){var question = this.survey.questions_attributes[index]if (question.id == null) {this.survey.questions_attributes.splice(索引,1)} 别的 {this.survey.questions_attributes[index]._destroy = "1"}},撤消删除:功能(索引){this.survey.questions_attributes[index]._destroy = null},保存调查:函数(){//创建一个新的调查如果(this.survey.id == null){this.$http.post('/surveys', { 调查:this.survey }).then(response => {Turbolinks.visit(`/surveys/${response.body.id}`)}, 响应 =>{控制台日志(响应)})//编辑现有调查} 别的 {this.$http.put(`/surveys/${this.survey.id}`, { 调查:this.survey }).then(response => {Turbolinks.visit(`/surveys/${response.body.id}`)}, 响应 =>{控制台日志(响应)})}},现有调查:函数(){返回 this.survey.id != null}}})}})

_form.html.erb

<%= content_tag :div,id:调查表",数据: {调查:survey.to_json(除了:[:created_at,:updated_at]),问题属性:survey.questions.to_json,}做%><label>调查名称</label><input qtype="text" v-model="survey.name"><h4>问题</h4><div v-for="(question, index) insurvey.questions_attributes"><div v-if="question._destroy == '1'">{{ question.title }} 将被删除.<button v-on:click="undoRemove(index)">撤消</button>

<div v-else><label>问题</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 }}</选项></选择><button v-on:click="removeQuestion(index)">Remove</button>

<小时/>

<button v-on:click="addQuestion">添加问题</button><br><button v-on:click="saveSurvey" >保存调查</button><%结束%>

解决方案

我遵循了相同的教程,并开始遇到使用具有更复杂嵌套属性的 JSON.parse 的问题.尝试使用 Jbuilder 构建您的 JSON 对象并查看 gon gem 以将您的 Rails 变量传递到 Javascript.使用 Rails 需要的嵌套命名查询数据库并将结果传递到 Javascript 文件会容易得多.例如...

survey = @surveyjson.id 调查.idjson.survey 做json.(survey, :user_id, :name)json.questions_attributes Survey.questions 做 |问题|json.(问题,:id,:title,:qtype,:_destroy)json.choices_attributes question.choices 做 |选择|json.(选择, :id, :ctext)结尾结尾结尾

它允许你做诸如...

var 调查 = gon.survey

代替...

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

您可以从控制器操作中传递 gon.jbuilder 并准备好定义的 JSON 对象并在 Vue 中可用.

I created one nested form by watching gorails tutorial It is fine and i done it. Issue started when i want to creat nested model under on other nested model. I have Survey model and it is main model. Then i added Question model and made form with vue.js. So I added Choice model under question ( you can notice in survey controller params) First problem is; i don't know how i can define/implemen in vue.js control.(hello_vue.js) And second importan point is: how i can create form elements in new.html

This is my survey.rb model:

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

and 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

This is nested model of 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

So finaly vue.js file:

 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 %>

解决方案

I followed this same tutorial and started running into issues using JSON.parse with more complex nested attributes. Try using Jbuilder to build your JSON objects and look into the gon gem to pass your Rails variables into Javascript. It'll be much easier to query your database and pass the results into your Javascript file using the nested naming that Rails needs. For example...

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

It allows you to do things like...

var survey = gon.survey

Instead of...

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

And you can pass gon.jbuilder from your controller action and have your defined JSON object ready and available in Vue.

这篇关于rails vue.js 深度嵌套(属性的属性)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆