You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Vue.js+Bootstrap实现带嵌套问题的动态调研表单求助

Hey there! Let's tackle your two problems one by one with practical Vue + Bootstrap + Kendo UI solutions that fit your dynamic survey form needs.


1. Implement Input/Date Picker Toggle & Build the Question Array with v-for Logic

First, we'll structure a flexible question array that defines both main Yes/No questions and their nested conditional fields. This array will drive the entire form via v-for, and we'll use conditional rendering to show/hide nested inputs based on the main question's answer.

Step 1: Define the Question Structure in Vue Data

Each question object will include:

  • id: Unique identifier for tracking responses
  • text: The question label
  • type: Fixed as yesno for main questions
  • nested: Array of conditional sub-questions (with their own type, showOn rule, and label)
data() {
  return {
    surveyResponses: {}, // Stores all form responses (main + nested)
    questions: [
      {
        id: "q1",
        text: "Question 1: Have you completed onboarding?",
        type: "yesno",
        nested: [
          {
            id: "q1_1",
            text: "Please provide your onboarding completion date:",
            type: "date",
            showOn: "yes" // Show only if main question is answered "Yes"
          }
        ]
      },
      {
        id: "q2",
        text: "Question 2: Do you need to submit a text explanation?",
        type: "yesno",
        nested: [
          {
            id: "q2_1",
            text: "Enter your explanation:",
            type: "input",
            showOn: "yes"
          },
          {
            id: "q2_2",
            text: "Enter your reference ID:",
            type: "input",
            showOn: "no" // Show only if main question is answered "No"
          }
        ]
      }
    ]
  };
}

Step 2: Render the Form with v-for & Conditional Toggles

Use Bootstrap for styling, v-for to loop through questions, and conditional directives (v-if) to show/hide nested fields based on the main Yes/No selection. For Kendo UI's date picker, we'll directly use its Vue component.

<template>
  <div class="container mt-5">
    <!-- Loop through main questions -->
    <div v-for="question in questions" :key="question.id" class="mb-4">
      <div class="card">
        <div class="card-body">
          <h5 class="card-title">{{ question.text }}</h5>
          <!-- Yes/No Radio Buttons -->
          <div class="form-check form-check-inline">
            <input
              class="form-check-input"
              type="radio"
              :id="`${question.id}_yes`"
              :value="'yes'"
              v-model="surveyResponses[question.id]"
            />
            <label class="form-check-label" :for="`${question.id}_yes`">Yes</label>
          </div>
          <div class="form-check form-check-inline">
            <input
              class="form-check-input"
              type="radio"
              :id="`${question.id}_no`"
              :value="'no'"
              v-model="surveyResponses[question.id]"
            />
            <label class="form-check-label" :for="`${question.id}_no`">No</label>
          </div>
        </div>
      </div>

      <!-- Render nested questions conditionally -->
      <div
        v-for="nestedQ in question.nested"
        :key="nestedQ.id"
        class="ml-5 mt-3"
        v-if="surveyResponses[question.id] === nestedQ.showOn"
      >
        <div class="form-group">
          <label>{{ nestedQ.text }}</label>
          <!-- Text Input -->
          <input
            v-if="nestedQ.type === 'input'"
            class="form-control"
            v-model="surveyResponses[nestedQ.id]"
          />
          <!-- Kendo UI Date Picker -->
          <kendo-datepicker
            v-else-if="nestedQ.type === 'date'"
            v-model="surveyResponses[nestedQ.id]"
            format="yyyy-MM-dd"
          ></kendo-datepicker>
          <!-- Dropdown Example (if needed) -->
          <select
            v-else-if="nestedQ.type === 'select'"
            class="form-control"
            v-model="surveyResponses[nestedQ.id]"
          >
            <option value="">Select an option</option>
            <option value="option1">Option 1</option>
            <option value="option2">Option 2</option>
          </select>
        </div>
      </div>
    </div>

    <!-- Preview All Responses (for testing) -->
    <div class="mt-5">
      <h4>Current Responses:</h4>
      <pre class="bg-light p-3">{{ surveyResponses }}</pre>
    </div>
  </div>
</template>

How This Works:

  • The surveyResponses object dynamically stores answers using question IDs as keys (e.g., surveyResponses.q1 = "yes").
  • Nested fields only render when the main question's answer matches the showOn value in the nested question config.
  • We use v-if with component types to toggle between input fields, Kendo date pickers, or dropdowns.

2. Bind All Radio Button Values to an Array/List

If you want a dedicated collection of just the main Yes/No radio responses (separate from nested fields), you can either:

Option 1: Use an Object (Simplest)

We already use surveyResponses to store radio values (e.g., surveyResponses.q1 = "yes"). To extract just radio answers, you can filter the object:

computed: {
  radioAnswers() {
    return Object.fromEntries(
      Object.entries(this.surveyResponses).filter(([key]) => 
        this.questions.some(q => q.id === key)
      )
    );
  }
}

Option 2: Use an Array (For Ordered Responses)

If you prefer an array of objects with question IDs and values, update your data and add a method to sync selections:

data() {
  return {
    radioAnswers: [], // Stores [{ qid: "q1", value: "yes" }, ...]
    // ... rest of your data
  };
},
methods: {
  updateRadioAnswer(qid, value) {
    // Find existing entry for the question
    const existingEntry = this.radioAnswers.find(item => item.qid === qid);
    if (existingEntry) {
      existingEntry.value = value;
    } else {
      this.radioAnswers.push({ qid, value });
    }
  }
}

Then update the radio button bindings to use the @change event instead of v-model:

<input
  class="form-check-input"
  type="radio"
  :id="`${question.id}_yes`"
  @change="updateRadioAnswer(question.id, 'yes')"
/>
<input
  class="form-check-input"
  type="radio"
  :id="`${question.id}_no`"
  @change="updateRadioAnswer(question.id, 'no')"
/>

Bonus: Add Input Validation

To implement validation via input props (as you mentioned), you can use Bootstrap's form validation classes alongside Vue's reactivity. For example, mark a nested input as required only when it's visible:

<input
  v-if="nestedQ.type === 'input'"
  class="form-control"
  v-model="surveyResponses[nestedQ.id]"
  :required="surveyResponses[question.id] === nestedQ.showOn"
/>

You can also integrate Vue's built-in validation or libraries like VeeValidate for more complex rules tied to your question config.

内容的提问来源于stack exchange,提问作者Rasik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:43:30