3

I'm creating my component library in vue, and I defined my component checkbox, the code is like this:

<template>
    <div class="checkboxcont" :class="{'checkboxcont-selected': isSelected}" @click="clickevent">
        <span class="j-checkbox">
            <input type="checkbox" />
        </span>
        <slot></slot>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                isSelected: false
            }
        },
        methods: {
            clickevent(event) {
                if(this.isSelected) {
                    this.isSelected = false;
                } else {
                    this.isSelected = true;
                }
            }
        },
    }
</script>

Now, I hope that when I click the checkbox to set the data "isSelected" false, I can give the component class "checkboxcont-selected-last", and when I click other checkbox component, the classname "checkboxcont-selected-last" can be removed, how can I listen my click event to finish it? I try to use native JavaScript code to add the classname of the dom, but it seemed to have nothing when I binded the classname of my component with Vue.js:

clickevent(event) {
    if(this.isSelected) {
        this.isSelected = false;
        this.$el.classList.add("checkboxcont-selected-last");
    } else {
        this.isSelected = true;
    }
}

What should I do to solve this problem, please?

Here is my style code using less:

<style lang="less" scoped rel="stylesheet/less">
    @import '../../mixin/mixin.less';
    .checkboxcont {
        display: inline-block;
        &:hover {
            cursor: pointer;
            .j-checkbox {
                border-color: @jbluelight;
            }
        }
    }
    .j-checkbox {
        position: relative;
        top: 0;
        left: 0;
        width: 12px;
        height: 12px;
        display: inline-block;
        border: 1px solid @border;
        border-radius: 3px;
        line-height: 12px;
        vertical-align: -3px;
        margin: 0 5px;
        z-index: 20;
        transition: all .2s linear;
        input {
            opacity: 0;
            position: absolute;
            left: 0;
            top: 0;
            visibility: hidden;
            /*display: none;*/
        }
    }
    .checkboxcont-selected {
        .j-checkbox {
            background: @jbluelight;
            border-color: @jbluelight;
            &:after {
                content: '';
                width: 4px;
                height: 7px;
                border: 2px solid white;
                border-top: none;
                border-left: none;
                position: absolute;
                left: 3px;
                top: 0;
                z-index: 30;
                transform: rotate(45deg) scale(1);
            }
        }
    }
</style>
<style lang="less" rel="stylesheet/less">
    @import '../../mixin/mixin.less';
    .checkboxcont-selected-last .j-checkbox {
        border-color: @jbluelight;
    }
</style>

My initial thought is that I add the class by using this.$el after I clicked the component, it can be accessed because I dispatched the click event, and I just can't access the other component:

if(this.isSelected) {
    this.isSelected = false;
    this.$el.classList.add("checkboxcont-selected-last")
} else {
    this.isSelected = true;
}

And I remove the class by using native HTML DOM operation when I dispatch the click event because I can not access the other component, so the complete definition of clickevent is that:

clickevent(event) {
    let selectedLast = document.querySelector(".checkboxcont-selected-last");
    if(selectedLast) {
        selectedLast.classList.remove("checkboxcont-selected-last")
    }
    if(this.isSelected) {
        this.isSelected = false;
        this.$el.classList.add("checkboxcont-selected-last")
    } else {
        this.isSelected = true;
    }
}

It looks good, but I can not add classname of my component when I use v-bind to bind my component's classname, is it wrong? And Is it unable to use native HTML DOM operation when I bind my component's classname with Vue?

Jorten
  • 35
  • 6
  • I would just like to mention that there is many component libraries for Vue and it is really enough so just consider to participate in some of them instead of creating new one. – Marek Urbanowicz Dec 21 '16 at 08:08
  • Can you try to elaborate? I am trying to understand what you want to achieve but I just can't. It would help if you would create fiddle with this case so it would be easier to help you. – Marek Urbanowicz Dec 21 '16 at 08:10
  • You are already using dynamic binding of HTML classes, which I noticed after posting the answer, so why do you need native JavaScript code to add the classes in DOM. – Saurabh Dec 21 '16 at 08:39
  • Yes, I can dynamically bind HTML class now, but it is useful in one component (I can only do this) , ***how can I do to click this component and remove another component's class, please?*** – Jorten Dec 21 '16 at 13:06

1 Answers1

0

A better way to dynamically add or remove class can be using v-bind:class. There are different ways you can add a dynamic class based on a vue data variable.

I see you are already using it:

<div class="checkboxcont" :class="{'checkboxcont-selected': isSelected}" @click="clickevent">

So here this div will have only one class : checkboxcont if isSelected is false, and two classes : checkboxcont and checkboxcont-selected if isSelected is true.

Edited:

Given that you want to add a class to DOM on another component, I can think of two ways:

  1. Using Web API: You can do following if you know the id of the element you want to add class using Element.className:

var d = document.getElementById("yourElem") d.className += " otherclass"

  1. Vuex way: You can have a centralised state provided by vue or use vuex to manage state, these state variables can be changed across components, and can be used to add/remove class dynamically.

You can have a look at my this answer to understand more about vuex.

tony19
  • 125,647
  • 18
  • 229
  • 307
Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • Perhaps I don't express my thought clearly, I can dynamically add my class by binding clickEvent, but it is useful in one component, how can I do when ***I click one checkbox(component 1), and remove the class of another checkbox(component 2)?*** – Jorten Dec 21 '16 at 13:02
  • I want to let my component's border light when I cancel click it, but when I click other checkbox, it's border should not be light, so I give a temp class for it, ***I added my style code using less, you can see it.*** – Jorten Dec 21 '16 at 13:14
  • The first way you gived, I try to use it in the end of my question, but it seemed to do nothing, was I wrong to use ***this.$el*** to change it's classname?And the second way I want to ask when I use Vuex, I must let user to write Vue.use(vuex), and I mentioned that I wanted to create a component library, so is it a good way to use ***Vuex***? – Jorten Dec 21 '16 at 14:57
  • @Jorten I don't think you can access element of other component using **this.$el**, besides the syntax you are using also seems wrong. Yes, Vuex is the standard way which is used among vue community to have shared data across different components, have a look at my answer [here](http://stackoverflow.com/questions/40953496/vue-shared-data-between-different-pages/40955110#40955110). – Saurabh Dec 21 '16 at 15:09
  • I understand your mean.Now I have two questions, the first is that I try to change classname in other component, and I would add it in my question, you can see, please. The second is that when I use ***vuex***, I must declare that: `Vue.use(vuex);` And when people use my component, they will import it: `import checkbox from "ChanotUI"` Is it use vuex automatically? Or they should declare `"Vue.use(vuex)"` again by themselves? – Jorten Dec 21 '16 at 15:21
  • @Jorten You only need to use `Vue.use(vuex)` only once in your app, like in app.js file – Saurabh Dec 21 '16 at 16:03
  • I use `Vue.use(vuex)` in the definition of my component, do the users need use `Vue.use(vuex)` again when they import my components? – Jorten Dec 21 '16 at 16:49
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131177/discussion-between-saurabh-and-jorten). – Saurabh Dec 21 '16 at 17:02