Search code examples
vuejs2toggleshow-hidebootstrap-vue

BootstrapVue Button States: Reset button when other button is clicked


Consider following code

<div id='app'>
  <div class="card shadow bg-light m-4">
    <b-table striped hover :items="items" :fields="fields" responsive>
      <template #cell(age)="data">
        <b-button :pressed.sync="data.item.age_visible" pill variant="outline-danger">
          <span v-if="data.item.age_visible">{{data.item.age}}</span>
          <span v-else>Show Age</span>
        </b-button>
      </template>
    </b-table>
  </div>
</div>
new Vue({
  el: "#app",
  data() {
    return {
      fields: ['first_name', 'last_name', 'age'],
      items: [
        { age: 40, age_visible: false, first_name: 'Dickerson', last_name: 'Macdonald' },
        { age: 21, age_visible: false, first_name: 'Larsen', last_name: 'Shaw' },
        { age: 89, age_visible: false, first_name: 'Geneva', last_name: 'Wilson' },
        { age: 38, age_visible: false, first_name: 'Jami', last_name: 'Carney' }
      ]
    }
  },
});

which gives you

enter image description here

When you click on "Show Age", the age is revealed. Try it on codepen.

My question:

When someone clicks in a different row on "Show Age", the age in the revealed row should now be hidden again. How can I achieve this?

Also let me know whether the column age_visible is actually necessary.

Versions

  • Vue 2.6.12
  • Bootstrap 4.6.0
  • BootstrapVue 2.21.2

Solution

  • I don't think age_visible is necessary. What the issue seems to be here is that you never do anything to a button that was clicked on before once you move to the next one. When you click on a new button, the last button should be back to its original state.

    My idea was to have something that keeps track of the current index in data() and then when you click on a button, it checks if the current index matches the button that was just clicked. If true, then it shows the age and if false then it hides it. The only weird CSS thing about my solution is that the button no longer stays red once it's clicked on unless you hover over it.

    Here's what I have

    new Vue({
      el: "#app",
      data() {
        return {
          currentIndex: -1,
          fields: ['first_name', 'last_name', 'age'],
          items: [
            { index: 0, age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
            { index: 1, age: 21, first_name: 'Larsen', last_name: 'Shaw' },
            { index: 2, age: 89, first_name: 'Geneva', last_name: 'Wilson' },
            { index: 3, age: 38, first_name: 'Jami', last_name: 'Carney' }
          ]
        }
      },
      methods: {
        setIndex(pendingIndex) {
          this.currentIndex = pendingIndex
        }
      }
    });
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" />
    <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
    <script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.min.js"></script>
    
    <div id='app'>
      <div class="card shadow bg-light m-4">
        <b-table striped hover :items="items" :fields="fields" responsive>
          <template #cell(age)="data">
            <b-button @click="setIndex(data.item.index)" pill variant="outline-danger">
              <span v-if="currentIndex === data.item.index">{{data.item.age}}</span>
              <span v-else>Show Age</span>
            </b-button>
          </template>
        </b-table>
      </div>
    </div>