3
votes

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.

4
did you try something like variant:(value)=>{return value>0?'danger':''success'} ?Boussadjra Brahim
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' arrayJack Casas

4 Answers

3
votes

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)
              }
            })
          }
        })
2
votes

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
votes

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.

1
votes

@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;
        }
      },