vue.jsvue-material

Vue Material - Styling the table buttons?


I am playing around with Vue and the Vue Material components, specifically the Table component.

What I would like to do is change the colour of the search icon/button within the table example which is titled Within cards with Pagination and Inline Edit but it seems that I must be missing something because I can not get it to change from the default of colour of grey and I am battling to understand why this is the case.

I have a basic page where I have included Vue along with the fonts and icons required for Vue material and the Javascript and CSS files that are required for it to work.

index.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Testing</title>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <link rel="stylesheet" href="https://cdn.rawgit.com/marcosmoura/vue-material/master/dist/vue-material.css" />
</head>
<body>
  <div id="app" v-md-theme="'default'">
    <md-table-card>
      <md-toolbar>
        <h1 class="md-title">Nutrition</h1>
        <md-button class="md-icon-button">
          <md-icon>filter_list</md-icon>
        </md-button>

        <md-button class="md-icon-button" @click="toggleSearch()">
          <md-icon v-if="searchEnabled" class="md-accent">search</md-icon>
          <md-icon v-else>search</md-icon>
        </md-button>
      </md-toolbar>

      <md-table md-sort="dessert" md-sort-type="desc" @select="onSelect" @sort="onSort">
        <md-table-header>
          <md-table-row>
            <md-table-head md-sort-by="dessert">Dessert (100g serving)</md-table-head>
            <md-table-head md-sort-by="calories" md-numeric md-tooltip="The total amount of food energy and the given serving size">Calories (g)</md-table-head>
            <md-table-head md-sort-by="fat" md-numeric>Fat (g)</md-table-head>
            <md-table-head md-sort-by="carbs" md-numeric>Carbs (g)</md-table-head>
            <md-table-head md-sort-by="protein" md-numeric>Protein (g)</md-table-head>
            <md-table-head>
              <md-icon>message</md-icon>
              <span>Comments</span>
            </md-table-head>
          </md-table-row>
        </md-table-header>

        <md-table-body>
          <md-table-row v-for="(row, rowIndex) in nutrition" :key="rowIndex" :md-item="row" md-auto-select md-selection>
            <md-table-cell v-for="(column, columnIndex) in row" :key="columnIndex" :md-numeric="columnIndex !== 'dessert' && columnIndex !== 'comment'" v-if="columnIndex !== 'type'">
              <md-table-edit
                :md-name="'comment' + columnIndex"
                :md-id="'comment' + columnIndex"
                md-placeholder="Add a comment"
                md-maxlength="120"
                v-model="nutrition[rowIndex].comment"
                v-if="columnIndex === 'comment'"></md-table-edit>

              <span v-if="columnIndex !== 'comment'"></span>
            </md-table-cell>
          </md-table-row>
        </md-table-body>
      </md-table>

      <md-table-pagination
        md-size="10"
        md-total="5"
        md-page="1"
        md-label="Rows"
        md-separator="of"
        :md-page-options="[5, 10, 25, 50]"
        @pagination="onPagination"></md-table-pagination>
    </md-table-card>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js" type="text/javascript"></script>
  <script src="https://cdn.rawgit.com/marcosmoura/vue-material/master/dist/vue-material.js" type="text/javascript"></script>
  <script src="app.js" type="text/javascript"></script>
</body>
</html>

app.js:

// Enable Vue Material
Vue.use(VueMaterial);

// Apply theme
Vue.material.theme.register('default', {
  primary: 'blue',
  accent: 'light-blue'
});

// Initialise Vue
new Vue({
  el: '#app',
  data: {
    nutrition: [{
      dessert: 'Frozen yogurt',
      type: 'ice_cream',
      calories: '159',
      fat: '6.0',
      carbs: '24',
      protein: '4.0',
      comment: 'Icy'
    }],
    selectedData: [],
    sort: {},
    page: {},
    searchEnabled: false
  },
  methods: {
    onSelect: function (data) {
      this.selectedData = data;
      this.$forceUpdate();
    },
    onSort: function (sort) {
      this.sort = sort;
    },
    onPagination: function (page) {
      this.page = page;
    },
    toggleSearch: function () {
      console.log(this.searchEnabled);
      if (this.searchEnabled) {
        this.searchEnabled = false;
      } else {
        this.searchEnabled = true;
      }
    }
  }
});

When I load the page I get the application with the table as with the example. When I click on the search icon, I can see the console log from the method toggleSearch() and it changes between boolean values as expected, however, the colour of the search icon is not changing.

Looking at the components HTML for the search button:

<md-button class="md-icon-button" @click="toggleSearch()">
  <md-icon v-if="searchEnabled" class="md-accent">search</md-icon>
  <md-icon v-else>search</md-icon>
</md-button>

I used a if / else condition to switch between the accented class and what I assume would be the default grey depending on the boolen value searchEnabled and this works with a stand alone button but just not inside of the table.

Could anyone suggest a reason as to why this is happening or how I should be going about styling of this button within the table. Any input or feedback would be greatly appreciated, many thanks!

(Bonus points if you can suggest if there is a way in Vue to apply a class conditionally, i.e. instead of using v-if, v-else and duplicating the icon element, is there another way for me to apply the class based on the boolean value and use only one icon element?)


Solution

  • Yes, You can do dynamic styling using VueJs, Here is documentation for the same. You can pass an object to v-bind:class to dynamically toggle classes:

    <md-button class="md-icon-button" @click="toggleSearch()">
      <md-icon v-bind:class="{ 'md-accent': searchEnabled }">search</md-icon>
    </md-button>
    

    The above syntax means the presence of the md-accent class will be determined by the truthiness of the data property searchEnabled.