Tribe Events Calendar Posts not fetching

I’ve been banging my head against a wall on this one for about 3 hours now. Basically, I want to access Tribe Events Calendar events posts in my website so I can include “Upcoming Events” and “Current Exhibitions” on the home page, which are in the events calendar, but I am unable to. Here is what I’ve done so far:

  1. I first tried to use the Tribe Events Calendar endpoint tribe/events/v1/events/ (the link will go to the endpoint on my WordPress instance) by adding it as a custom post type in my frontity.settings.js file as such in state.source:

     postTypes: [{
             type: 'tribe_events',
             endpoint: 'tribe/events/v1/events',
             archive: '/events'
           }]
    

    Then I added this to my root index.js:

    actions: {
      theme: {
        beforeSSR: async ({ actions }) => {
          await actions.source.fetch('/tribe/events/v1/events')
        }
      }
    }
    

    Then in the necessary component:

    const upcomingEventLink = `/${post.acf.upcoming_event.post_name}/${post.acf.upcoming_event.post_name}`
    
    useEffect(() => {
      actions.source.fetch(upcomingEventLink)
    }, [])
    
    const upcomingEventData = state.source.get(upcomingEventLink)
    return (<pre>{(upcomingEventData.isReady) ? state.source[post.acf.upcoming_event.post_type][post.acf.upcoming_event.ID].featured_media : 'nothing'}</pre>)
    

    But that didn’t work, my hunch is it’s because of their custom namespace. Also, we’ll be coming back to this route later. Here is the error I get:

       Proxy
       ​<target>: {…}
       ​errorStatus: 404
       ​errorStatusText: "Not Found"
       ​is404: true
       ​isError: true
       ​isFetching: false
       ​isReady: true
       ​link: "/tribe_events/treasure-box-workshop-with-artist-jannette-vanderhoop/"
       ​page: 1
       ​query: Object {  }
       ​route: "/tribe_events/treasure-box-workshop-with-artist-jannette-vanderhoop/"
       ​<prototype>: Object { … }
       ​<handler>: Object { get: get(target, key, receiver), has: has(target, key), ownKeys: ownKeys(target), … }
    
  2. I exposed tribe_events post types using the example found in WordPress documentation and can now see that at /wp-json/wp/v2/tribe-events (the link will go to the endpoint on my WordPress instance):

    add_filter( 'register_post_type_args', 'expose_tribe_events_to_rest', 10, 2 );
    
    function expose_tribe_events_to_rest( $args, $post_type ) {
     if ('tribe_events' === $post_type) {
     	$args['show_in_rest'] = true;
    
     	// Optionally customize the rest_base or rest_controller_class
     	$args['rest_base']             = 'tribe-events';
     	$args['rest_controller_class'] = 'WP_REST_Posts_Controller';
     }
    
     return $args;
    }
    

    This is also not working even though I can see that the REST route has been added. This is the error I get from that:

     Proxy
       <target>: {…}
       errorStatus: 404
       errorStatusText: "You have tried to access content at route: /tribe_events/treasure-box-workshop-with-artist-jannette-vanderhoop/ but it does not exist"
       is404: true
       isError: true
       isFetching: false
       isReady: true
       link: "/tribe_events/treasure-box-workshop-with-artist-jannette-vanderhoop/"
       page: 1
       query: Object {  }
       route: "/tribe_events/treasure-box-workshop-with-artist-jannette-vanderhoop/"
       <prototype>: Object { … }
       <handler>: Object { get: get(target, key, receiver), has: has(target, key), ownKeys: ownKeys(target), … }
    

    The other issue with this is that I don’t get any of the metadata associated with the event, such as start time, end time, venue, organizer, etc. This is probably on the WordPress side and may have to do with the rest_controller_class or I may need to manually add the data to the posts via this method.

  3. I’ve also tried various incantations of the fetch in the beforeSSR and the useEffect because I am never sure if I should be fetching the post type, tribe_events, or the endpoint, which is either events or tribe-events.

What might be worth noting is I have another component that requires a custom post referenced in the current post’s advanced custom fields meta data and that is working just fine. I have registered the custom post type in WordPress, registered it in frontity.settings.js just as I did for the tribe_event, I fetch the data in beforeSSR and in useEffect, and I’m able to grab the featured image as well as I don’t get an error returned.

I’m going off of code I found here in the forums. Namely this thread contained code regarding using an ACF post object to populate a featured image and this thread where @mburridge suggests using custom post type definitions to add events calendar post types to state.source for use later.

After sleeping on it, I thought I’d try a couple more things:

  1. Based on what @phn did here, I thought I’d make my own handler:
    const tribeEventsHandler = {
       name: 'tribe-events',
       priority: 10,
       pattern: '/tribe-events/:id',
       func: async ({ route, params, state, libraries }) => {
         const { api } = libraries.source
         const { id } = params
    
         const response = await api.get({
           endpoint: `/tribe/events/v1/events/${id}`
         })
    
         const data = await response.json()
         const currentPageData = state.source.data[route]
    
         Object.assign(currentPageData, {
           id,
           data,
           isEvent: true
         })
       }
     }
    
    Then I added it to my libraries.source.handlers array and added an await actions.source.fetch('tribe-events') but that gives me the following error:
    post type from endpoints \"posts,pages,media\" with slug \"treasure-box-workshop-with-artist-jannette-vanderhoop\" not found
    
  2. I tried this plugin from this post and while it did expose the events in the REST API with all the data I needed for all events, I still couldn’t access individual events in Frontity. I get the following error:
    You have tried to access content at route: /tribe_events/treasure-box-workshop-with-artist-jannette-vanderhoop/ but it does not exist
    

I’ll keep at it but if anyone has any tips, that would be greatly helpful.

Hi @david1

There’s quite a lot going on here. It will be really difficult for us to analyse your issue in the abstract. It would help to have access to your project code and your source data. Could you provide a link to a repo with your code so we can see it and clone it please, and is your WP source data on a live server that we can access? If you can provide those then we’ll try our best to help you. Thanks.

Hey @mburridge,

Thanks for getting back to me. The repository is at https://gitlab.artlyticalmedia.com/artlytical-media/mv-museum-frontity-theme and please check out branch MVM-203-current-exhibition-01. The WP source data is on the live server http://staging.mvmuseum.org. What I’m trying to get working is in packages/mvmuseum-theme/src/components/home.js. Right now I have it working for the object_of_the_day ACF custom field, which is a post object field, but there is also a post object for upcoming_event that is really buggy. Let me know if you need me to change anything on the WP side.

Hi @david1

I’ve cloned your repo and checked out the MVM-203-current-exhibition-01 branch. I can’t find the tribeEventsHandlerhandler in your code.

Do you want to use the http://staging.mvmuseum.org/wp-json/tribe/events/v1/events/ endpoint or the http://staging.mvmuseum.org/wp-json/wp/v2/tribe_events endpoint? I would suggest using the former, but you’ll need a handler for it.

Hey @mburridge,

Thanks for taking a look into this. I was able to get it sorted today, I guess I just needed to step back for a couple days for the clarity to kick in.

For anyone else wanting to do this, here is how I’ve managed it:

I added tribeEventsHandler as such and added it to the libraries.source.handlers array:

const tribeEventsHandler = {
  name: 'tribe-events',
   priority: 10,
   pattern: '/tribe-events/:id',
   func: async ({ route, params, state, libraries }) => {
     const { api } = libraries.source
     const { id } = params

     const response = await api.get({
       endpoint: `/tribe/events/v1/events/${id}`
     })

     const data = await response.json()
     const currentPageData = state.source.data[route]

     Object.assign(currentPageData, {
       id,
       data,
       isEvent: true
     })
   }
}

Then the way that events is fetched is similar to how I was fetching global ACF options pages:

const upcomingEventLink = `/tribe-events/${post.acf.upcoming_event.ID}`
const upcomingEventData = state.source.get(upcomingEventLink)

However, to get an image attachment, I have to do it differently than I would for a custom post type at the moment because state.source doesn’t find "tribe-events" post types by default (perhaps I need to fetch them in my actions.theme.beforeSSR?). However, I can get the featured image’s URL from the upcomingEventData.data.image.url.

1 Like

Hello @david1 , @mburridge

I’ve been following this thread in order to get the data from The Event Calendars plugin. I have this code in my frontity.settings.js:

{
    type: 'tribe_events',
    endpoint: 'tribe/events/v1/events',
    archive: '/events'
 }

Then I copied your tribeEventsHandler in a handler.js file. After that, I made an import in the index.js file as follow:

import tribeEventsHandler from './components/handler'

and added it to my libraries.source.handlers array in this way:

actions: {
    theme: {
      init: ({ libraries }) => {
        libraries.source.handlers.push(tribeEventsHandler);
      },
    }, 
  }

I was expecting to have some data related when I execute frontity.state.source in the console, But still I can’t see any data related to the events that I created.

Also I tried to make frontity.state.source.get("/events") or frontity.state.source.get("/tribe/events/v1/events") but seems like there’s no data.

I guess I’m missing a lot here since I don’t understand completely how the handler works. Hope you guys can give some hints or a solution to this. Thank you in advance.