Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuejs + Materializecss select field

I have this code in my template:

<div class="input-field col s6">
    <select v-on:change="selectChaned" v-model="item.size">
        <option value="" disabled selected>Choose your option</option>
        <option v-on:click="optionClicked" v-for="size in case_sizes" v-bind:value="{{ size }}">{{ size }}</option>
    </select> 
    <label for="size">Size</label>
</div>

According to Materializecss docs, I call $('select').material_select(); to transform default select field into something cutie. What it also does - it replaces <select> and <option> tags with <ul> and <li>. As a result I can't access value of item.size in my ViewModel js file. I even tried to listen for a click on option field and call optionClicked method (which should simply alert a message then), tried to listen for selectChaned. Nothing.

How can I get option value in ViewModel?

p.s. just for information: I only have problem with select field. Input field for example works fine:

<input placeholder="" name="name" type="text" class="validate" v-model="item.name">

In ViewModel I'm able to access item.name

like image 235
Desprit Avatar asked Nov 14 '15 01:11

Desprit


2 Answers

It seems that Materialize doesn't dispatch any events so I couldn't find an elegant solution. But it does seem that the following Vuejs directive + jQuery workaround is working:

Vue.directive("select", {
    "twoWay": true,

    "bind": function () {
        $(this.el).material_select();

        var self = this;

        $(this.el).on('change', function() {
            self.set($(self.el).val());
        });
    },

    update: function (newValue, oldValue) {
        $(this.el).val(newValue);
    },

    "unbind": function () {
        $(this.el).material_select('destroy');
    }
});

And then in your HTML – bind <select> using v-select instead of v-model.

like image 54
Denis Mysenko Avatar answered Nov 04 '22 15:11

Denis Mysenko


Vue.js 2.0

Template:

<div v-text="selected"></div>
<material-select v-bind="selected = selected || options[0].value" v-model="selected">
     <option v-for="option in options" :value="option.value" v-text="option.name"></option>
</material-select>

Component:

"use strict";

Vue.component("material-select", {
    template: '<select><slot></slot></select>',
    props: ['value'],
    watch: {
        value: function (value) {

            this.relaod(value);
        }
    },
    methods:{
      relaod : function (value) {

          var select = $(this.$el);

          select.val(value || this.value);
          select.material_select('destroy');
          select.material_select();
      }
    },
    mounted: function () {

        var vm = this;
        var select = $(this.$el);

        select
            .val(this.value)
            .on('change', function () {

                vm.$emit('input', this.value);
            });

        select.material_select();
    },
    updated: function () {

        this.relaod();
    },
    destroyed: function () {

        $(this.$el).material_select('destroy');
    }
});
like image 27
Дмитрий Гуров Avatar answered Nov 04 '22 15:11

Дмитрий Гуров