VUE 2 with Bootstrap 4 - Radio button action not working when using data-toggle=“buttons”

懵懂的女人 提交于 2021-02-07 07:15:50

问题


I have the following code:

<template>
    <div class="btn-group" data-toggle="buttons">
        <label class="btn btn-outline-dark active">
            <input type="radio" name="grp" v-model="channel" value="vh1" checked> VH1
        </label>
        <label class="btn btn-outline-dark">
            <input type="radio" name="grp" v-model="channel" value="mtv"> MTV
        </label>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                channel: 'mtv'
            }
        },
        watch: {
            channel: function(newValue) {
                console.log('value has been changed to ' + newValue);
            }
        }
     }
</script>

When I click on a radio button, nothing happens. But when I removed the "data-toggle="buttons" attribute for the styling, then it starts working! Can anyone help me find a work around here?

Edit

For those of you who don't know, data-toggle is from bootstrap button plugin, it adds extra styles and functionality to the buttons you are making. Check out the docs here: https://getbootstrap.com/docs/4.0/components/buttons/#toggle-states


回答1:


Remove data-toggle and set active class by :class="{ 'active': channel === [value] }" for each input.




回答2:


Finally got the solution

After long hours of searching, I was able to come up with a way to hack into the buttons.

Step 1

Change the above template to the following (removed v-model from the inputs)

<template>
    <div class="btn-group" data-toggle="buttons" v-radio="channel">
        <label class="btn btn-outline-dark active">
            <input type="radio" name="grp" value="vh1" checked> VH1
        </label>
        <label class="btn btn-outline-dark">
            <input type="radio" name="grp" value="mtv"> MTV
        </label>
    </div>
</template>

This solution was pretty difficult to find, and the solution was pretty hacky, but it got the job done.

Step 2 (UPDATED 6/18/2018)

Create a directive

In my case, since I was using single file components, I needed to bring it directives in the following way:

radio.js

export default {
    inserted: function (el, binding) {
        var btns = $(el).find('.btn');
        var radioGrpName = $(btns[0]).find('input')[0].name;
        $("input[name='" + radioGrpName + "'][value='" + binding.value + "']").closest('.btn').button('toggle');
    },
    bind: function (el, binding, vnode) {
        var btns = $(el).find('.btn');
        btns.each(function () {
            $(this).on('click', function () {
                var v = $(this).find('input').get(0).value;
                (function set(obj, str, val) {
                    str = str.split('.');
                    while (str.length > 1) {
                        obj = obj[str.shift()];
                    }
                    return obj[str.shift()] = val;
                })(vnode.context, binding.expression, v);
            })
        })
    }
}

What this does is it binds a jquery click event to each radio button found in the div containing the v-radio. The second part where I'm doing function set (copied from the answer in reference), it checks to see if there's any dots in the expression, otherwise it sets the value of vnode.context["channel"], which updates the model. The bind hooks up to events before the component is loaded so it can be ready to fire off the internal workings of the radio button.

The inserted function is called after bind, during the physical insertion of the component into the parent node. So when you set an initial state (no event fired), the component will automatically reflect the value set in data.

Step 3

add directives radio to the script

import radio from '../../directives/radio'
<script>
    export default {
        directives: {
            radio: radio  
        },
        data() {
            return {
                channel: 'mtv'
            }
        },
        //you can use computed property, but you need get and set
        watch: {
             channel: function(newValue) {
                 console.log('value has been changed to ' + newValue);
             }
         }
     }
 </script>

Using these links as references:

  • Old custom directive hack using vue 1
  • Update model from custom directive


来源:https://stackoverflow.com/questions/49023790/vue-2-with-bootstrap-4-radio-button-action-not-working-when-using-data-toggle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!