Adam Silva
Adam Silva

Reputation: 1047

VueJS Reactive Array with filters

I have a notification list with two filters (Show All, Show Unread). I load all of the notifications when the component is created and then call the filter Show All.

created() {
   axios.get('user/notifications').then(response => {
       this.notifications = response.data;
       this.showAll();
   }).catch(e => {
       console.log(e);
   });
 },

Here are the Show All and Show Unread methods:

showAll() {
     this.filteredNotifications = this.notifications;
},
showUnread() {
    this.filteredNotifications = _.filter(this.notifications, notif => {
          return notif.read_at === null;
    });
},

I'm iterating the array like this:

<li v-for="notif in filteredNotifications">
    <span @click="toggleNotification(notif)"></span>
</li>

And here I'm toggling the notification:

toggleNotification(notification) {
    axios.put('user/notification/' + notification.id + '/toggle', {_method: 'PUT'}).then(response => {
         notification.read_at = notification.read_at == null ? true : null;
    }).catch(e => {
         console.log(e);
    });
}

I'm trying to make it so, when I'm in the Show Unread filter, whenever I toggle a notification it will be removed from that filter. It can't be removed from the original array because when I click on Show All, I have to see all notifications.

At the moment, when I'm in the See Unread Filter, if I toggle a notification it changes the notification read_at to true, but doesn't remove it from the list. Only when I click the filter again does it refresh.

I could easily solve this by putting a flag in each filter, and then in the toggleNotification I could check which flag is active and call it's method manually, but that's too dirty for me. Any help?

Upvotes: 1

Views: 1550

Answers (1)

WebMan
WebMan

Reputation: 384

Your methods look like okay. But if you want to notification mark as read then send request to back end database to set read_at = currentDate. When the request ended succesfully just exclude read notification by its index from this.filteredNotifications array and Vue will re render based on new array.

<li v-for="(notif, index) in filteredNotifications">
    <span @click="toggleNotification(notif, index)"></span>
</li>

Then in your method:

toggleNotification(notification, index) {
    axios.put('user/notification/' + notification.id + '/toggle', {_method: 'PUT'}).then(response => {
       notification.read_at = notification.read_at == null ? true : null;
       this.filteredNotifications.splice(index, 1)
    }).catch(e => {
       console.log(e);
});

If you want to re render based on response, then in response send back the all unread notifications and set this.filteredNotifications = response.

Upvotes: 1

Related Questions