Search code examples
javascriptvue.jsvcalendar

API response in V-Calendar customData attribute


I am trying to use the V-calendar library linked here in a Vue component. However, I seem to be having an issue on wrapping my head around how to do this properly. I am using the Google Calendar API to get events from a particular calendar, but the API returns an array of objects, whose objects contain their own objects and it goes down even further. I've been able to access my events and drill down to what I need, but now I need to figure out how to get the date span for each event.

The general idea is to basically duplicate the original Google calendar but only show particular events.

I hope this makes sense, I am happy to answer any additional questions if there are any.

Code:

<template>
  <v-calendar >
  </v-calendar>
</template>

<script>
  import {calendarAPI} from '../../views/auth/keys/googleCalendar.js';
  import { setupCalendar, Calendar} from 'v-calendar'
  import axios from 'axios';
  import 'v-calendar/lib/v-calendar.min.css';

export default {
 data() {
  return {
    attributes: [
      {
        customData:  axios.get('https://www.googleapis.com/calendar/v3/calendars/' + calendarAPI.CALENDAR_ID+ '/events?key=' + calendarAPI.API_KEY)
        .then(res => {
            const data = res.data.items;

            const filteredResult = data.filter((item, i) => {
                if(item.summary.includes("Holiday") && !item.summary.includes("Student")) {
                    return item
                }
            });
            console.log(filteredResult)
        })
      }
    ]
  }

    }
}
</script>

And here is an example of what the API call is returning:

(3) [{…}, {…}, {…}]
0:
created: "2019-03-19T19:00:22.000Z"
creator: 
end: {date: "2019-04-20"}
etag: ""3106050066842000""
htmlLink: 
iCalUID: "28231"
id: "_68s34cph"
kind: "calendar#event"
organizer: 
sequence: 0
start: {date: "2019-04-19"}
status: "confirmed"
summary: "Easter Holiday"
updated: "2019-03-19T19:50:33.421Z"
visibility: "public"
__proto__: Object
1:
created: "2019-03-19T19:00:22.000Z"
creator: 
end:
date: "2019-04-23"
__proto__: Object
etag: ""3106050066842000""
htmlLink: 
iCalUID: "28232"
id: "_68s34cpi"
kind: "calendar#event"
organizer: 
sequence: 0
start: {date: "2019-04-22"}
status: "confirmed"
summary: "Easter Holiday"
updated: "2019-03-19T19:50:33.421Z"
visibility: "public"
__proto__: Object
2:
created: "2019-03-19T19:00:22.000Z"
creator: 
end: {date: "2019-05-28"}
etag: ""3106050066842000""
htmlLink: 
iCalUID: "28233"
id: "_68s34cpj"
kind: "calendar#event"
organizer:
sequence: 0
start: {date: "2019-05-27"}
status: "confirmed"
summary: "Memorial Day Holiday"
updated: "2019-03-19T19:50:33.421Z"
visibility: "public"
__proto__: Object
length: 3

EDIT

I've worked on some more code to filter out unnecessary results. Here is the updated vue component:

<template>
    <v-calendar
    :attributes='attributes'
    is-expanded>
    </v-calendar>
</template>

<script>
import {calendarAPI} from '../../views/auth/keys/googleCalendar.js';
import { setupCalendar, Calendar} from 'v-calendar'
import axios from 'axios';
import 'v-calendar/lib/v-calendar.min.css';

export default {
  data() {
        // grabbing data from the api
       const holidays = axios.get('https://www.googleapis.com/calendar/v3/calendars/' + calendarAPI.CALENDAR_ID+ '/events?key=' + calendarAPI.API_KEY)

        // getting the response from the api
        .then(res => {

            // filtering the inital object the api returns
            const data = res.data.items;

            //conditional filtering to only grab holidays that aren't student
            const filteredResult = data.filter((item, i) => {
                if(item.summary.includes("Holiday") && !item.summary.includes("Student")) {
                    return item
                }
            });

            // getting the values from the api object and mapping through them to get only the values that are needed
            const dates = filteredResult.map((item, i) => {
               const timespan = {

                   start: new Date(item.start.date),
                   end: new Date(item.end.date)
               }
               return timespan
           })
            // should return only the new object
           return dates
        })

    return {
      attributes: [
        {
          highlight: {
            backgroundColor: '#ff8080', // Red
            borderColor: '#ff6666',
            borderWidth: '2px',
            borderStyle: 'solid',
          },
          contentStyle: {
            color: 'white',
          },
          dates: holidays.then(data => {
                let newdata = data
                console.log(newdata)
                return newdata
            })
        },
        {
          highlight: {
            backgroundColor: '#66b3cc', // Turquoise
            borderColor: '#53a9c6',
            borderWidth: '2px',
            borderRadius: '5px',
          },
          contentStyle: {
            color: 'white',
          }
        },
      ],
    };
  },
};
</script>

And console output:

0: {start: Thu Apr 18 2019 19:00:00 GMT-0500 (Central Daylight Time), end: 
Fri Apr 19 2019 19:00:00 GMT-0500 (Central Daylight Time)}
1: {start: Sun Apr 21 2019 19:00:00 GMT-0500 (Central Daylight Time), end: Mon Apr 22 2019 19:00:00 GMT-0500 (Central Daylight Time)}
2: {start: Sun May 26 2019 19:00:00 GMT-0500 (Central Daylight Time), end: Mon May 27 2019 19:00:00 GMT-0500 (Central Daylight Time)}
length: 3
__proto__: Array(0)

I am finally seeing something on the calendar, but all of the dates are highlighted now. I think the issue may be that the holiday function is returning a promise, not the values

Image: image of issue


Solution

  • I ended up switching libraries to vue-fullcalendar and changed up the code a little bit. I think the problem was that I was trying to input a promise into the Date's value. It took a long time to figure that out, and I only did by console.log() the variable I was returning. The code below gives the expected result and Although it may not be the most efficient answer, I managed to figure it out.

    As mentioned here is the code:

    <template>
      <full-calendar :events="events"></full-calendar>
    </template>
    
    <script>
    import { calendarAPI } from "../../views/auth/keys/googleCalendar.js";
    import axios from "axios";
    import { FullCalendar } from "vue-full-calendar";
    import "fullcalendar/dist/fullcalendar.css";
    
    export default {
      components: {
        FullCalendar
      },
      data() {
        return {
          events: []
        };
      },
      mounted() {
        // grabbing data from the api
        const getHolidays = () =>
          axios
            .get(
              "https://www.googleapis.com/calendar/v3/calendars/" +
                calendarAPI.CALENDAR_ID +
                "/events?key=" +
                calendarAPI.API_KEY
            )
            // getting the response from the api
            .then(res => {
              // filtering the inital object the api returns
              const data = res.data.items;
    
              //conditional filtering to only grab holidays that aren't student
              const filteredResult = data.filter((item, i) => {
                if (
                  item.summary.includes("Holiday") &&
                  !item.summary.includes("Student")
                ) {
                  return item;
                }
              });
    
              // getting the values from the api object and mapping through them to get only the values that are needed
              const dates = filteredResult.map((item, i) => {
                console.log(item);
                const timespan = {
                  id: i,
                  title: item.summary,
                  description: item.summary,
                  start: item.start.date,
                  end: item.end.date
                };
                return timespan;
              });
              // should return only the new object
              return dates;
            });
    
        getHolidays().then(data => {
          let events = data;
          this.events = events;
        });
    
        const holidays = this.events;
      }
    };
    </script>