Aurilie
Aurilie

Reputation: 199

Not able to v-bind:style in vue

I'm trying to change my text to red when there is a change to the textbox, but even though my value turned to true my text doesn't change color. I thought about using the conditional v-bind:style, but I'm not sure if I've done it wrong.

Here is my code

    <template>
        <div>
            <table class="table table-sm table-bordered">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Price</th>
                    </tr>
                </thead>

                <tbody>
                    <tr v-for="product in products">
                        <td>{{product.name}}</td>
                        <td>
                            <input  @change="onChange(product.price)"
                                    :style="[dirty ? 'color: red' : '']"
                                    v-model="product.price"
                            >
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </template>

    <script>
    export default {
        props: ['products],
        data() {
            return {
                dirty: false
            }
        },
        methods: {
            onChange(value)
            {
                return this.dirty = true;
            }
        },
        mounted(){

        }
    }
    </script>

Upvotes: 1

Views: 2060

Answers (1)

hamid niakan
hamid niakan

Reputation: 2871

var vm = new Vue({
  el: '#app',
  data: {
    products: [{
      name: 'one',
      price: 1
    }, {
      name: 'two',
      price: 2
    }],
    dirty: false,
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Price</th>
      </tr>
    </thead>

    <tbody>
      <tr v-for="(product, i) in products" :key="i">
        <td>{{product.name}}</td>
        <td>
          <input @focus="dirty = product.name" :style="{color: dirty === product.name ? 'red' : 'black'}">
        </td>
      </tr>
    </tbody>
  </table>
</div>

use an object in your style binding and use a computed to return a value based on the condition.

for example in your template you can have:

<input :style="{ color: conditionalColor}">

then in your computed you have:

computed: {
  conditionalColor() {
    return this.dirty ? 'red' : '';
  }
}

and you can also read this part of the documentation for further info:

style binding object syntax

Edit: so because you are using a v-for and use a general variable i.e. dirty to toggle the style binding, when you change it all the input colors get changed, what you can do is to make the variable be specific to just one element (also it is a best practice to use key whenever you are using a v-for to avoid weird behavior from vue).

here is what I put together to give you an idea on how to do this, I used the dirty variable as a temporary value holder of the product name that its input is in focus right now and in the style binding check if this temporary variable match the product.name or not and by this I can toggle the focused input color between 'red' and 'black'.

also if you change @focus to @input you can see the color toggle effect only on the current input.

run the code and see for yourself (hope this helps)

Upvotes: 1

Related Questions