Bootstrap-select и Vue.js: selectpicker («обновить») не работает

Я пытаюсь реализовать плагин bootstrap-select (найден здесь https://developer.snapappointments.com/bootstrap-select/) в приложение ruby ​​on rails с Vue.js в качестве фреймворка javascript.

Цель состоит в том, что в одном разделе вы можете выбрать категорию, а в другом — всех учителей, доступных для этой категории. Для этого я использую axios и vue, чтобы сделать запрос к моему собственному API и использовать его для заполнения второго выбора, и он отлично работает с простым полем выбора, однако я хочу, чтобы отображался выбор начальной загрузки, я знаю, что плагин имеет функция "selectpicker('refresh')", чтобы сделать возможной перезагрузку опции, но моя консоль браузера утверждает, что selectpicker не является функцией, когда я вызываю ее в своем экземпляре vue, однако я могу вручную запустить ее в консоли браузера, и она работает по назначению

Мой код:

js:

Vue.use(VueAxios, axios)
    document.addEventListener('DOMContentLoaded', () => {
      if(document.getElementById('enrollment_form')) {
      var app = new Vue({
        el: '#enrollment_form',
        data: {
          CategoryValue: null,
          TeacherValue: null,
          teachers: null,
        },
        methods: {
          fetchTeachers() {
            this.axios.get('/api/teachers/' + this.licenceTypeValue).then(response => (this.teachers = response.data))
              $('.selectpicker').selectpicker('refresh');
          }
        }, 
      })
    }})

Посмотреть:

       <div class="row">
          <div class="col-lg-5">
            <div class="form-group">
              <%= f.label :category %>*<br />
              <%= f.collection_select(
                  :category,
                  Category.all,
                  :id,
                  :catgegory_name,
                  {include_blank: true},
                  {
                    class: 'form-control selectpicker',
                    "v-model" => "CategoryValue",
                    "v-on:change" => "fetchTeachers"

                  }
              )%>
            </div>
          </div>  
        </div>

        <div class="row">
          <div class="col-lg-5">
            <div class="form-group">
              <label for="teacher_id">Teacher</label>
              <div>
                <select id="teachers-list" class='form-control selectpicker' v-model="TeacherValue" data-fieldname = "TeacherValue">
                  <option label="" ></option>
                  <option v-for="teacher in teachers" :value="teacher.id"> {{teacher.name}}  </option>
                </select>
              </div>
            </div>
          </div>  
        </div>

        <div>
          <%= f.hidden_field :teacher_id, {"v-model" => "TeacherValue"} %>
        </div>

Наконец-то мой application.js

//= require rails-ujs
//= require activestorage
//= require jquery
//= require jquery_ujs
//= require popper
//= require bootstrap
//= require bootstrap-select

Я был бы очень признателен, если бы кто-то мог помочь, поскольку я просто не могу понять, что делать


person Jose David Bayona    schedule 04.12.2018    source источник
comment
Я искал, как использовать Vue и jQuery вместе, потому что ваш вопрос заставил меня задуматься, возможно ли это. Проверьте это: vuejsdevelopers.com/2017/05/20 /vue-js-safely-jquery-плагин   -  person Katie.Sun    schedule 04.12.2018


Ответы (2)


Попробуйте изменить на следующее:

var app = new Vue({
    el: '#enrollment_form',
    data: {
        CategoryValue: null,
        TeacherValue: null,
        teachers: null,
    },
    methods: {
        fetchTeachers() {
            // Get the Vue object in a variable so you can use it in the "then" 
            // since 'this' context changes in the "then" handler function.
            let theVue = this;

            this.axios
                .get('/api/teachers/' + this.licenceTypeValue)
                .then(response => {
                    theVue.teachers = response.data;
                    // Call bootstrap-select's 'refresh' using Vue's $nextTick function 
                    // to ensure the update is complete before bootstrap-select is refreshed.
                    theVue.$nextTick(function(){ $('#teachers-list').selectpicker('refresh'); });
                });
        }
    }, 
})

Я столкнулся с этой проблемой в приложении, которое разрабатывал, и написал статью с более подробным объяснением., включая неработающие и работающие примеры. В моих примерах параметры изменяются через JavaScript без AJAX, но концепция та же.

В приведенном выше коде вы вызываете «обновление» начальной загрузки, используя функцию Vue $nextTick, которая ожидает завершения обновления объекта Vue перед выполнением кода, переданного вызову $nextTick. (см. $nextTick в документации по Vue)

Примечание. Вы также можете выполнить более общее обновление в обработчике события update в Vue, добавив:

updated: function(){
  this.$nextTick(function(){ $('.selectpicker').selectpicker('refresh'); });
}

Имейте в виду, что это всегда будет обновлять все выборки начальной загрузки, которые используют один и тот же класс selectpicker. Обновление будет происходить при каждом обновлении данных vue, включая те, которые не связаны с рассматриваемым ‹select›, что расточительно и потенциально может вызвать проблемы с производительностью.

Я считаю, что наилучшей практикой является обновление только ‹select›, который нуждается в обновлении, в тот момент, когда он нуждается в обновлении (в вашем случае, когда возвращается вызов AJAX и свойство «учителя» было обновлено).

person ThatOneGuy    schedule 30.12.2018

Если вы запустите его в методе тайм-аута, он будет обновлен.

 setTimeout(function () {
            $(".selectpicker").selectpicker("refresh");
        }, 1000);
person Suphi Atlı    schedule 08.04.2020
comment
Привет @Suphi Atlı, добро пожаловать в stackoverflow! Вы отвечаете на старый вопрос, которому больше 1 года. Пожалуйста, попробуйте ответить на новые вопросы, это будет более полезно. И проверьте свой ответ в предварительном просмотре перед отправкой. Отступ кода неверен. - person Archer; 08.04.2020