Reg
Reg

Reputation: 77

Migrating Global notifications with Vue from Vue1 to Vue2

There is this fiddle of Global notifications with Vue that was written for Vue1 https://jsfiddle.net/Linusborg/wnb6tdg8/

const NotificationStore = {
  state: [], // here the notifications will be added

  addNotification: function (notification) {
    this.state.push(notification)
  },
  removeNotification: function (notification) {
    this.state.$remove(notification)
  }
}

var Notification = Vue.extend({
    template: '#notification',
  props: ['notification'],
  data: function () {
    return { timer: null }
    },
  ready: function () {
  let timeout = this.notification.hasOwnProperty('timeout') ? this.notification.timeout : true
  if (timeout) {
    let delay = this.notification.delay || 3000
      this.timer = setTimeout(function () {
        this.triggerClose(this.notification)
      }.bind(this), delay)
    }
  },

  methods: {
    triggerClose: function (notification) {
        clearTimeout(this.timer)
      this.$dispatch('close-notification', notification)
    }
  }
})

var Notifications = Vue.extend({
    template: '#notifications',
  components: {
    notification: Notification
  },
  data () {
    return {
      notifications: NotificationStore.state
    }
  },
  methods: {
    removeNotification: function (notification) {
      NotificationStore.removeNotification(notification)
    }
  }
})

Vue.transition('fade', {
  enterClass: 'fadeInDown', // class of animate.css
  leaveClass: 'fadeOutDown' // class of animate.css
})

var App = new Vue({
  el: '#app',
  components: {
    'notifications': Notifications
  },
  data() {
    return {
            // no Data Nessessary. Notifications are stored in the NotificationStore
    }
  },
  methods: {
    showSuccessMessage: function () {
        NotificationStore.addNotification({
        title: "Success!!",
        text: "A Success Message",
        type: "success",
        timeout: true
      })
    },
    showAlertMessage: function () {
        NotificationStore.addNotification({
        text: "An Alert Message, without a title",
        type: "alert"
        // timeout not specified - defaults to true
        // delay not specified, defaults to 3000
      })
    },
    showStickyMessage: function () {
        NotificationStore.addNotification({
      title: "Sticky!!",
        text: "This message will not time out, you have to click the close button",
        type: "primary",
        timeout: false // won't disappear on it's own
      })
    }
  }
})

I am trying to rewrite it for Vue 2, but having difficulties with replacing the $remove with something that will work the same way. Trying to use splice instead, didn't do the trick (probably because I didn't do it correctly)

Here is the new code with the changes that I have made (without the needed change of the $remove): https://jsfiddle.net/rzubty4c/

const NotificationStore = {
  state: [], // here the notifications will be added

  addNotification: function (notification) {
    this.state.push(notification)
  },
  removeNotification: function (notification) {
    //this.state.$remove(notification)
  }
}

var Notification = Vue.extend({
    template: '#notification',
  props: ['notification'],
  data: function () {
    return { timer: null }
    },
  created() {
  let timeout = this.notification.hasOwnProperty('timeout') ? this.notification.timeout : true
  if (timeout) {
    let delay = this.notification.delay || 3000
      this.timer = setTimeout(function () {
        this.triggerClose(this.notification)
      }.bind(this), delay)
    }
  },

  methods: {
    triggerClose: function (notification) {
        clearTimeout(this.timer)
      this.$emit('close-notification', notification)
    }
  }
})

var Notifications = Vue.extend({
    template: '#notifications',
  components: {
    notification: Notification
  },
  data () {
    return {
      notifications: NotificationStore.state
    }
  },
  methods: {
    removeNotification: function (notification) {
      NotificationStore.removeNotification(notification)
    }
  }
})


var App = new Vue({
  el: '#app',
  components: {
    'notifications': Notifications
  },
  data() {
    return {
            // no Data Nessessary. Notifications are stored in the NotificationStore
    }
  },
  methods: {
    showSuccessMessage: function () {
        NotificationStore.addNotification({
        title: "Success!!",
        text: "A Success Message",
        type: "success",
        timeout: true
      })
    },
    showAlertMessage: function () {
        NotificationStore.addNotification({
        text: "An Alert Message, without a title",
        type: "alert"
        // timeout not specified - defaults to true
        // delay not specified, defaults to 3000
      })
    },
    showStickyMessage: function () {
        NotificationStore.addNotification({
      title: "Sticky!!",
        text: "This message will not time out, you have to click the close button",
        type: "primary",
        timeout: false // won't disappear on it's own
      })
    }
  }
})

Could you please advise what should be the code in the removeNotification function instead of the original $remove?

Upvotes: 1

Views: 244

Answers (1)

Bert
Bert

Reputation: 82459

Use splice.

removeNotification: function (notification) {
    this.state.splice(this.state.indexOf(notification),1)
}

Additionally, you should use a key with v-for. See the documentation.

In 2.2.0+, when using v-for with a component, a key is now required.

<notification v-for="notification in notifications" :key="notification" :notification="notification" @close-notification="removeNotification" >

Your updated fiddle.

You might want to generate an id property for each notification to use for the key, but for now, I simply used the notification itself.

Upvotes: 1

Related Questions