在 Bootstrap Vue 中动态更改 select 输入

Dynamically change select input in Bootstrap Vue

我正在尝试以 Bootstrap-Vue 形式 select 设置一些对象,这是我通过 JSON 获得的。 JSON 由来自以下领域的教师对象组成:

[
  {
    "id": 1,
    "name": "John",
    "surname": "Doe",
    "email": "john.doe@gmail.com"
  }
]

我要做的是将名字和姓氏放在 select 列表中,即全名。

我已经设法通过计算 属性 通过处理列表来做到这一点。 但现在我希望当我 select 一位老师时,课程列表会根据所选老师进行过滤。

为此,我需要老师的电子邮件,我无法恢复,已经处理了老师以获得全名。 因此,我什至无法根据所选教师更新课程列表。

这是模板的代码:

<b-form-group
  id="input-group-3"
  label="Docente:"
  label-for="input-3"
>
  <b-form-select
    v-model="teacher"
    :options="teachers"
    value-field="item"
    text-field="fullName"
    required
    @change="filterCourse"
  ></b-form-select>
  <div class="mt-3">
    Selected: <strong>{{ teacher }}</strong>
  </div>
</b-form-group>

这是脚本代码:

import { mapGetters, mapActions } from "vuex";
export default {
  data() {
    return {
      teacher: "",
      course: "",
    };
  },

  created: function() {
    this.GetActiveTeachers();
    this.GetActiveCourses();
  },

  computed: {
    ...mapGetters({
      ActiveTeacherList: "StateActiveTeachers",
      ActiveCourseList: "StateActiveCourses",
      FilteredTeacherList: "StateTeacherByCourse",
      FilteredCourseList: "StateCourseByTeacher",
    }),

    teachers: function() {
      let list = [];
      this.ActiveTeacherList.forEach((element) => {
        let teacher = element.name + " " + element.surname;
        list.push(teacher);
      });
      return list;
    },
  },

  methods: {
    ...mapActions([
      "GetActiveTeachers",
      "GetActiveCourses",
      "GetCourseByTeacher",
      "GetTeacherByCourse",
      "AssignTeaching",
    ]),

    async filterCourse() {
      const Teacher = {
        teacherEmail: "john.doe@gmail.com", // For testing purpose
      };
      try {
        await this.GetCourseByTeacher(Teacher);
      } catch {
        console.log("ERROR");
      }
    },

    async filterTeacher() {
      const Course = {
        title: "Programming", // For testing purpose
      };
      try {
        await this.GetTeacherByCourse(Course);
      } catch {
        console.log("ERROR");
      }
    },
  },
};

您可以执行以下两种不同的选择。

一个方法是自己在 select 中生成 <option>,使用 v-for 遍历你的老师,并绑定 email 属性 到 value,并在选项中显示 namesurname

这将使您的 <b-select> 的 v-model return 成为所选教师的电子邮件,然后您可以在过滤器中使用它。

new Vue({
  el: '#app',
  data() {
    return {
      selectedTeacher: null,
      activeTeachers: [{
          "id": 1,
          "name": "Dickerson",
          "surname": "Macdonald",
          "email": "dickerson.macdonald@example.com"
        },
        {
          "id": 2,
          "name": "Larsen",
          "surname": "Shaw",
          "email": "larsen.shaw@example.com"
        },
        {
          "id": 3,
          "name": "Geneva",
          "surname": "Wilson",
          "email": "geneva.wilson@example.com"
        }
      ]
    }
  }
})
<link href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.js"></script>


<div id="app">
  <b-select v-model="selectedTeacher">
    <option v-for="teacher in activeTeachers" :value="teacher.email">
      {{ teacher.name }} {{ teacher.surname }}
    </option>
  </b-select>

  {{ selectedTeacher }}
</div>


另一种选择是将您的计算结果更改为 return 一个 对象数组 而不是您当前正在做的简单字符串。

默认情况下,如果您在 options 属性中使用对象数组,则 <b-select> 需要属性 valuetext

在这里,您可以将每位教师的 email 绑定到 value,并将 namesurname 绑定到 text 道具。

这将使您的 <b-select> 的 v-model return 成为所选教师的电子邮件,然后您可以在过滤器中使用它。

参考:https://bootstrap-vue.org/docs/components/form-select#options-property

new Vue({
  el: '#app',
  data() {
    return {
      selectedTeacher: null,
      activeTeachers: [{
          "id": 1,
          "name": "Dickerson",
          "surname": "Macdonald",
          "email": "dickerson.macdonald@example.com"
        },
        {
          "id": 2,
          "name": "Larsen",
          "surname": "Shaw",
          "email": "larsen.shaw@example.com"
        },
        {
          "id": 3,
          "name": "Geneva",
          "surname": "Wilson",
          "email": "geneva.wilson@example.com"
        }
      ]
    }
  },
  computed: {
    teacherOptions() {
      return this.activeTeachers.map(teacher => ({
        value: teacher.email,
        text: `${teacher.name} ${teacher.surname}`
      }));
    }
  }
})
<link href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.js"></script>


<div id="app">
  <b-select v-model="selectedTeacher" :options="teacherOptions"></b-select>

  {{ selectedTeacher }}
</div>

您当前使用的是 Bootstrap Vue 为表单 selects(字符串数组)提供的最简单的表示法。

我建议您改用他们的 object notation,这样您就可以指定 text(您在列表中显示的内容)与 value(发送到的内容)分开select 的 v-model).

这样,您将能够访问您需要的教师对象的所有数据,同时仍然能够仅显示您想要的数据。

我们可以通过将 teachers 计算的 属性 中的 forEach() 换成 map():

来做到这一点
teachers() {
  return this.ActiveTeacherList.map((teacher) => ({
    text: teacher.name + " " + teacher.surname,
    value: teacher
  }));
},

然后,您需要做的就是更新您的 filterCourse() 处理程序以使用新语法,例如:

async filterCourse() {
  const Teacher = {
    teacherEmail: this.teacher.email,
  };
  try {
    await this.GetCourseByTeacher(Teacher);
  } catch {
    console.log("ERROR");
  }
},

最后一点,如果你不想或不需要完整的对象作为值,那么你可以将它塑造成你需要的任何东西,这就是这种语法的美妙之处。
例如,您需要全名和电子邮件,而不是以下部分:

value: { 
  fullName: teacher.name + " " + teacher.surname,
  email: teacher.email
}