Izaskun DA
Izaskun DA

Reputation: 39

input value in vuejs using css :not[value=""]

I'm using Bootstrap-Vue in a VueJS project, and it's being impossible using a class..

I have the next input

<div class="input__wrapper">
   <b-form-input
     v-model="idOrNameSelected"
     class="textfield"
     :class="{'input--empty': idOrNameSelected != null}"
     @keydown.enter.native="onSubmit" />
     <label
       class="input__label">Service id or name</label>
</div>

In my script section I defined idOrNameSelected like:

data () {
    return {
      idOrNameSelected: ''
    }
  }

In my scss file I have a rule like

&:focus ~ .input__label,
&:not([value=""]) ~ .input__label {
  top: 8px;
  pointer-events: none;
}

And when I put any text in my input never is using this css rule, why?????

Thanks

Upvotes: 0

Views: 1727

Answers (2)

dev-cyprium
dev-cyprium

Reputation: 768

Here's the problem. The CSS logic doesn't know about Vue observers or v-model so it doesn't update the way you think. Take a step back and try this simple example:

HTML

<input class="in" type="text" value="bar" />
<label class="lab">Test</label>

CSS

.in:not([value="foo"]) ~ .lab {
  color: crimson;
}

As you can see, the label is now red. Now try changing the value="foo" you'll see the label switches colors. But, what you should note here is that it doesn't have any sort of 2-way binding on the CSS itself, but actually just takes the current value in the actual DOM.

To provide you with an actual solution, I would use a class binding in this case. You can read about them here: https://v2.vuejs.org/v2/guide/class-and-style.html

Essentially, it allows you to dynamically add/remove a class based on some true condition. And you can actually use your v-model in there.

Here's an example of how I would do it:

<template>
  <div id="app">
    <input type="text" v-model="model">
    <label :class="{error: model === ''}">Label</label>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return { model: "" };
  }
};
</script>

<style scoped>
.error {
  color: crimson;
}
</style>

Upvotes: 2

Troy Morehouse
Troy Morehouse

Reputation: 5435

@dev-cyprium is correct regarding Vue not placing the attribute value on the input element when using v-model (value is actually a domProp on the element)

There is a trick you can do with data attributes though:

<template>
  <div>
    <b-form-input id="the-input" v-model="value" :data-value="value"></b-form-input>
    <label for="the-input">Hello World</label>
  </div>
</template>

<style>
  input.form-control ~ label {
    color: red;
  }
  input.form-control[data-value=""] ~ label {
    color: blue;
  }
</style>

<script>
  export default {
    data() {
      return {
        value: ''
      }
    }
  }
</script>

Upvotes: 1

Related Questions