【问题标题】:How to make sure all radiobox questions have been interacted with如何确保所有单选框问题都已交互
【发布时间】:2021-11-23 05:17:27
【问题描述】:

用户需要为每个任务选择是或否的小应用程序。除非用户回答了所有问题,否则不应允许用户离开页面。我在表单底部添加了一个按钮,模拟beforeRouterLeave 行为。

我的问题是关于simulateBeforeRouteLeave() 函数。如何检查是否所有问题都已回答以允许用户离开?

附言。这是从一个更大的项目中截取的。原始数据来自 API,并且没有像本例中那样进行硬编码。

CodeSandbox

App.vue

<template>
  <parent-component
    v-for="task in tasks.data"
    :key="task.id"
    :taskData="task"
    @update-form-data="handleChange"
  >
  </parent-component>
  <button
    class="my-2 border-2 border-red-500"
    @click="simulateBeforeRouteLeave"
  >
    simulateBeforeRouteLeave
  </button>
</template>

<script>
import parentComponent from "./components/parentComponent.vue";
export default {
  components: {
    parentComponent,
  },
  methods: {
    simulateBeforeRouteLeave() {
      //Need HELP Here! How do I write this IF statement?
      if ("Options_NOT_Selected") {
        alert("Please select all options");
      } else {
        console.log("Allow user to leave 'next()'");
      }
    },
    handleChange(e) {
      const objIndex = this.tasks.data.findIndex((obj) => obj.id === e.id);
      this.tasks.data[objIndex].status = e.status;
    },
  },
  data() {
    return {
      markAll: false,
      tasks: {
        data: [
          {
            id: 1,
            name: "Task 1",
            status: null,
          },
          {
            id: 2,
            name: "Task 2",
            status: null,
          },
          {
            id: 3,
            name: "Task 3",
            status: null,
          },
        ],
      },
    };
  },
};
</script>

父组件.vue

<template>
  <div class="py-2">
    <div>
      <input
        type="radio"
        :id="taskData.id + 'Yes'"
        :name="taskData.name"
        :value="taskData.value"
        @change="updateData"
      />
      <label :for="taskData.id">{{ taskData.name }} Yes</label>
    </div>
    <div>
      <input
        type="radio"
        :id="taskData.id + 'No'"
        :name="taskData.name"
        :value="taskData.value"
      />
      <label :for="taskData.id">{{ taskData.name }} No</label>
    </div>
  </div>
</template>

<script>
export default {
  props: ["taskData"],
  methods: {
    updateData(e) {
      this.$emit("update-form-data", {
        id: this.taskData.id,
        status: 1,
      });
    },
  },
  data() {
    return {};
  },
};
</script>

【问题讨论】:

    标签: javascript vue.js vuejs3


    【解决方案1】:

    您可以在App.vue 中添加数据属性selected: [],。 您可以在mounted 挂钩中添加状态已设置为selected 数组的任务。 然后在方法中将收到的项目推送到selected数组:

    handleChange(e) {
      if (!this.selected.filter(s => s.id === e.id).length) this.selected.push(e)
    

    然后在simulateBeforeRouteLeave()比较selectedtasks.data的长度

    Vue.component('parent', {
      template: `
        <div class="py-2">
        <div>
          <input
            type="radio"
            :id="taskdata.id + 'Yes'"
            :name="taskdata.name"
            :value="taskdata.value"
            @change="updateData"
          />
          <label :for="taskdata.id">{{ taskdata.name }} Yes</label>
        </div>
        <div>
          <input
            type="radio"
            :id="taskdata.id + 'No'"
            :name="taskdata.name"
            :value="taskdata.value"
          />
          <label :for="taskdata.id">{{ taskdata.name }} No</label>
        </div>
      </div>
      `,
      props: ["taskdata"],
      methods: {
        updateData(e) {
          this.$emit("update-form-data", {
            id: this.taskdata.id,
            status: 1,
          });
        },
      },
    })
    
    new Vue({
      el: '#demo',
      methods: {
        simulateBeforeRouteLeave() {
          if (this.selected.length < this.tasks.data.length) {
            alert("Please select all options");
          } else {
            console.log("Allow user to leave 'next()'");
          }
        },
        handleChange(e) {
          if (!this.selected.filter(s => s.id === e.id).length) this.selected.push(e)
          const objIndex = this.tasks.data.findIndex((obj) => obj.id === e.id);
          this.tasks.data[objIndex].status = e.status;
        },
        updateStatuses() {
          const stat = this.tasks.data.filter(t => t.status)
          if (stat) stat.forEach(s => this.selected.push(s))
        },
      },
      mounted() {
        this.updateStatuses()
      },
      data() {
        return {
          markAll: false,
          selected: [],
          tasks: {
            data: [
              { id: 1, name: "Task 1", status: 1, },
              { id: 2, name: "Task 2", status: null, },
              { id: 3, name: "Task 3", status: null,  },
            ],
          },
        };
      },
    })
    
    Vue.config.productionTip = false
    Vue.config.devtools = false
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="demo">
      <parent
        v-for="task in tasks.data"
        :key="task.id"
        :taskdata="task"
        @update-form-data="handleChange"
      >
      </parent>
      <button
        class="my-2 border-2 border-red-500"
        @click="simulateBeforeRouteLeave"
      >
        simulateBeforeRouteLeave
      </button>
      {{selected}}
    </div>

    【讨论】:

    • 感谢您回答@Nikola。这在某种程度上是有效的。但是通过在两个选项之间切换很容易破坏它。我可以点击Task 1 Yes,然后切换到Task 1 No,然后回到Task 1 Yes,就会满足if条件
    • 嘿@Nikola。再次感谢您帮助我。同样的问题仍然存在 - 现在只需要更多的点击。我已经提到这是一个来自更大应用程序的小型 sn-p,其中数据来自 API。我在原始问题中没有提到它,但检索到的数据可能会将status 设置为1。意味着它有一个答案。因此,除非用户更改该选项,否则不会调用 handleChange() 函数。我希望得到一个答案,我可以以某种方式从 app.vue 中跟踪每个单选框并查看它被选中。
    • 好的,请再次检查,现在您可以包含已设置状态的任务
    猜你喜欢
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2010-09-27
    • 1970-01-01
    • 2017-08-23
    相关资源
    最近更新 更多