I'm iterating through a list to generate calendars, the issue is each generator function has the same this.addToCalendar()
function. I'd like to know how I could condense this into only being called once, rather than in each function.
The main generators I'd like to look at are the ones within method
, where I am generating calendar links as well as calling an external api.
CSS has been removed to focus on JS logic.
<template>
<div>
<ul>
<li v-for="(calendar, i) in calendars" :key="i">
<button @click="calendar.generator">
<span>{{ calendar.type }}</span>
</button>
</li>
</ul>
<button @click="setExpanded(false)">
Close
</button>
</div>
</template>
<script>
import {
ICalendar,
GoogleCalendar,
OutlookCalendar,
YahooCalendar,
} from 'datebook'
import { mapActions, mapGetters } from 'vuex'
export default {
data() {
return {
calendars: [
{ type: 'Apple', generator: this.generateAppleCalendar },
{ type: 'Google', generator: this.generateGoogleCalendar },
{ type: 'Outlook', generator: this.generateOutlookCalendar },
{ type: 'Yahoo', generator: this.generateYahooCalendar },
],
success: null,
error: null,
}
},
computed: {
...mapGetters({
event: 'event/event',
expanded: 'calendar/expanded',
userType: 'user/userType',
}),
eventLocation() {
return `${this.event.location_street}, ${this.event.location_city}, ${this.event.location_state}. ${this.event.location_zip}`
},
generateConfig() {
const config = {
title: this.event.title,
location: this.eventLocation,
description: this.event.description,
start: new Date(this.event.start_time),
end: new Date(this.event.end_time),
}
return config
},
},
methods: {
...mapActions({
setExpanded: 'calendar/setExpanded',
}),
generateAppleCalendar() {
const icalendar = new ICalendar(this.generateConfig)
icalendar.download()
this.addToCalendar()
},
generateGoogleCalendar() {
const googleCalendar = new GoogleCalendar(this.generateConfig)
this.openInNewTab(googleCalendar.render())
this.addToCalendar()
},
generateOutlookCalendar() {
const outlookCalendar = new OutlookCalendar(this.generateConfig)
this.openInNewTab(outlookCalendar.render())
this.addToCalendar()
},
generateYahooCalendar() {
const yahooCalendar = new YahooCalendar(this.generateConfig)
this.openInNewTab(yahooCalendar.render())
this.addToCalendar()
},
openInNewTab(url) {
const win = window.open(url, '_blank') // Opening a new tab with the url
win.focus() // Focussing the users browser to new tab
},
async addToCalendar() {
let url
if (this.userType === 'guest') {
url = `event/${this.event.id}/add-guest-user`
} else {
url = `event/${this.event.id}/guest`
}
const response = await this.$axios.post(url)
if (response.status === 201) {
this.success = true
} else {
this.error = true
}
},
},
}
</script>
1 Answer 1
I'd like to know how I could condense this into only being called once, rather than in each function.
One option would be to make a method that accepted the calendar or type and called the associated method
methods:
generateCalendar(type) {
const generateMethod = `generate${type}Calendar`
if (typeof this[generateMethod] === 'function')
this[generateMethod]()
this.addToCalendar()
}
}
Then pass the type:
<button @click="generateCalendar(calendar.type)">
If the only property being accessed in the loop was that type property then destructuring assignment would allow it to be simplified:
<li v-for="({ type }, i) in calendars" :key="i">
<button @click="generateCalendar(type)">
<span>{{ calendar.type }}</span>
</button
Alternatively, with using the method above the generator
properties of the calendars could be removed, and calendars
could perhaps just be an array of strings.
Also, it seems that three of the four calendar methods are nearly identical other than the class of calendar object created: generateGoogleCalendar
, generateOutlookCalendar
and generateYahooCalendar
. A generic method could be used to replace those three methods (and accept the calendar type as a parameter to be used to dynamically invoke a constructor) or create them dynamically in a loop.
Explore related questions
See similar questions with these tags.
addToCalendar
? Do all calendars require the call? Are you expecting only one valid calendar, some calendars to be successful, or all calendars to setthis.success = true
? What should happen to calendars that result inthis.error = true
? Do you know ahead of instantiating calendars which you want? \$\endgroup\$