3

So I'm using Bootstrap Vue with this test app. I'm trying to change the variant of a table cell depending on the value of it. Unfortunately, the variant parameter will not take a function, so I'm out of ideas on how to achieve this.

This is my code:

var app = new Vue({
    el: '#app',
    data: {    
        items: [],      //Will be populated through AJAX
        fields: [
        {              
            key: 'Vendedor',
            label: 'Vendedor'                 
        },       
        {              
            key: 'OBJETIVO',
            label: 'Objetivo',
            formatter: (value) => { return parseFloat(value).toFixed(2)},
            variant: estiloObjetivo //THIS IS NOT WORKING
        }
      ]
    },
    methods: {
        Cargar: function () {
            var salesperson = getCookie('salespersonCode');
            var url_servicio = 'http://MywebService/';
            var self = this;
            $.ajax({
                type: 'GET',
                url: url_servicio + 'ventas/' + salesperson,
                dataType: "json", // data type of response                  
                success: function(data){            
                    self.items = data           
                }
            });
        },
        estiloObjetivo (value) {
                if value > 0 //I need my cell variant to change depeding on this value
                 return 'danger'
                else 
                 return 'success'

        }
    }
})

This is my HTML part:

<div id="app">  
    <button v-on:click="Cargar">Cargar</button>
    <b-table striped hover :fields="fields" :items="items"></b-table>
</div>

Any ideas on how to style a Bootstrap-vue cell dynamically?

This is the way it's done in the docs, it's actually set in the "items" array, but how is this useful in cases like mine where I get the data from a web service?:

{
    salesperson: 'John',
    Objetivo: 2000,
    _cellVariants: { salesperson: 'success', Objetivo: 'danger'}
  },

So I guess what I need is a way to set the I need is to set the _cellVariants parameter of each element in the 'items' array.

2
  • did you try something like variant:(value)=>{return value>0?'danger':''success'} ? Commented Jan 6, 2019 at 20:21
  • no luck.. variant: (value) => { return 'danger'} -> THIS IS IGNORED (No style) variant: 'danger' -> THIS WORKS. Anyway, I think this will affect the whole column, not just the row I need. What I need is to set the _cellVariants parameter of each element in the 'items' array Commented Jan 6, 2019 at 20:26

4 Answers 4

3

You likely need a computed property. Computed properties automatically update on changes to the reactive variables that they depend on.

The following example implements a computed property, styledItems, which you must use in place of items in the template. It returns a 1-deep copy of items, i.e. a new array containing a copy of each item, with the extra _cellVariants property added.

new Vue({
      data: {
        items: [ /* your data here */ ]
      },
      methods: {
        estiloObjetivo: value => (value > 0) ? 'danger' : 'success'
      },
      computed: {
        styledItems() {
          return this.data.map(datum =>
            Object.assign({}, datum, {
              _cellVariants: {
                Objetivo: this.estiloObjetivo(datum.Objetivo)
              }
            })
          }
        })
Sign up to request clarification or add additional context in comments.

Comments

2

If you want to add variant to items you could use a computed property called cptItems and define it as follows:

computed:{
     cptItems(){
        return this.items.map((item)=>{
               let tmp=item;
                item.OBJETIVO>0?tmp.variant='danger':tmp.variant='success';
                return tmp;

        })  
        }

and use that property inside your template like :

<b-table .... :items="cptItems"></b-table>

1 Comment

Brilliant! marking this as correct as both answers are fundamentally the same. A computed property where I "edit" the data is what I needed!
2

I was sure the answers above would solve my own issue but they did not. I found a different way to color table cells: https://github.com/bootstrap-vue/bootstrap-vue/issues/1793

This is aside from using variants to color a table cell. Instead, we utilize tdclass and a function.

<script>
  new Vue({
    el: '#itemView',
    data() {
      return {
        fields: [
          {
            key: 'Objetive',
            sortable: true,
            thClass: 'text-nowrap',
            tdClass: (value, key, item) => {
              return 'table-' + this.getColor(item);
            }
          }
        ],
      };
    },
    methods: {
      getColor(item) {
        return item.Objetive > 0 ? 'danger' : 'success';
      },
    },
  });
</script>

For my own use-case, I needed to compare two cells of the same row, then apply a class to one.

...
      {
        key: 'DEMAND_QTY',
        sortable: true,
        thClass: 'text-nowrap',
        tdClass: (value, key, item) => {
          return 'table-' + this.demandStatusColor(item);
        },
      },
      { key: 'TOTAL_DEMAND', sortable: true, thClass: 'text-nowrap' },
    ],
  };
},
methods: {
  demandStatusColor(item) {
    return item.DEMAND_QTY < item.TOTAL_DEMAND ? 'danger' : 'success';
  },
}
...

Perhaps this will help someone, if not OP.

Comments

1

@John answer worked for me. I don't have enough reputation to make comment or useful

tdClass: (type, key, item) => {
        switch (type) {
          case "value":
            return "bg-warning text-white";
            break;
          case "value":
            return "bg-danger text-white";
            break;
          case "value":
            return "bg-info text-white";
            break;
          default:
            break;
        }
      },

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.