Skip to content
Advertisement

How to toggle items from grid and list view in Vuejs?

    isGridView: true,
    isListView: true,

    methods: {
            
            switchView: function() {
                
          this.isGridView = !this.isGridView;
          
            },

            switchData: function () {

                this.isListView = !this.isListView;
            }
  <div class="product-grid1">item1</div>
     <div class="product-grid2">item2</div> 
     <div class="product-grid3">item3</div>
     
      <div class="product-list1">item1</div>
     <div class="product-list2">item2</div> 
     <div class="product-list3">item3</div>
     
      <div id="app-gridview">

            <div>
                <button class="button" v-on:click="switchView()"></button>
                <button class="button" v-on:click="switchData()"></button>
            </div>

            <div v-bind:class="[ isGridView ? 'grid-wrapper' : 'list-wrapper' ]">

                <div class="grid-row" v-if="isGridView">
                    <div class="grid-header" v-for="name in gridData.columns">{{ name }}</div>
                </div>

                <!-- GridView structure -->
                <div v-if="isGridView" class="grid-row" v-for="row in gridData.data">
                    <div class="list-row-item" v-for="name in gridData.columns">
                        <div>{{ row[name] }}</div>
                    </div>
                </div>

                <!-- ListView structure -->
                <div v-if="!isGridView" class="list-row" v-for="row in gridData.data">
                    <img v-bind:src="row.ImagePath" class="list-image" />
                    <div class="list-property">
                        <div class="list-row-item" v-for="name in gridData.columns">
                            <div class="list-property-name">{{ name }}</div>
                            <div>{{ row[name] }}</div>
                        </div>
                    </div>
                </div>

            </div>

I tried to implement the list and the grid view, Where I need to toggle between each one. For that i have taken isGrid and isList set to true, And from vue side i am trying to place ternary operator, And switch between each other.

Can you please help me on toggle from the list and grid view.

Advertisement

Answer

When you create a component whose view can be changed, I suggest that you use the container-presentational component pattern. Really easy to keep track, and it’s a breeze to add a new “view” of the data.

// this is the grid view
// this is a presentational component:
// only displays what is passed through props
Vue.component("GridView", {
  props: ["users"],
  computed: {
    headers() {
      if (!this.users.length) return []
      return Object.keys(this.users[0])
    },
  },
  template: `
    <table>
      <thead>
        <tr>
          <th
            v-for="header in headers"
            :key="header"
          >
            {{ header }}
          </th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="user in users"
          :key="user.id"
        >
          <td
            v-for="(val, key) in user"
            :key="user.id + '-' + key"
          >
            {{ val }}
          </td>
        </tr>
      </tbody>
    </table>
  `
})

// this is the list view
// this is a presentational component:
// only displays what is passed through props
Vue.component("ListView", {
  props: ["users"],
  template: `
    <ol>
      <li
        v-for="user in users"
        :key="user.id"
      >
        <div
          v-for="(val, key) in user"
          :key="user.id + '-' + key"
        >
          {{ key }}: {{ val }}
        </div>
      </li>
    </ol>
  `
})

// this component handles the data:
// fetching, mapping, transforming, etc.
// this is a renderless component
Vue.component("DataContainer", {
  data() {
    return {
      users: []
    }
  },
  mounted() {
    this.fetchUsers()
  },
  methods: {
    async fetchUsers() {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/users')
        const json = await response.json()
        this.users = json.map(({
          id,
          name,
          username,
          email
        }) => ({
          id,
          name,
          username,
          email
        }))
      } catch (err) {
        console.error(err)
      }
    }
  },
  render(h) {
    // renders nothing, just provides the data
    // by passing it through "users"
    return this.$scopedSlots.default({
      users: this.users,
    })
  },
})

// the Vue instance
new Vue({
  el: "#app",
  data() {
    return {
      layout: "list-view",
    }
  },
  methods: {
    switchView() {
      this.layout = this.layout === "list-view" ? "grid-view" : "list-view"
    }
  },
  template: `
    <div>
      <button
        @click="switchView"
      >
        SWITCH VIEW
      </button>
      <data-container>
        <template
          #default="{ users }"
        >
          <component
            :is="layout"
            v-bind="{ users }"
          />
        </template>
      </data-container>
    </div>
  `,
})
table {
  border-collapse: collapse;
}

table,
tr,
th,
td {
  border: 1px solid black;
}

td,
th {
  padding: 4px 8px;
}

th {
  background-color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<div id="app"></div>

I understand that this is a bit further away from correcting a v-if condition-handling – but this setup would help you create flexible, extensible & maintainable solution.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement