Get data from route as JSON for jQuery/fullcalendar


#1

How do I get JSON from store for jQuery/fullcalender?

component template:

{{yield}}

component JS:

export default Component.extend({
  didInsertElement() {
    $('.jquerycal').fullCalendar({
      events: this.get('events')
  },
  willDestroyElement() {
    $('.jquerycal').fullCalendar().destroy();
  }
});

first approach was hardcoding some array with data, which works:

export default Route.extend({
  model() {
    return [{
      type: 'events',
      id: '96',
      title: 'All Day Event',
      start: '2018-10-01',
      color: '#783f53'
    },...]
  }
});

then tried another route, which works as well (with plain json returned):

export default Route.extend({
  model() {
   return new RSVP.Promise(function(resolve) {
     later(function() {
       let data = Ember.$.getJSON('http://someurl.com/data?start=2018-08-27&end=2018-10-08');
       resolve(data);
      }, 400);
   });
  }
});

but now, with the following route, I got stuck. I use mirage to get the data.

export default Route.extend({
  model() {
    return this.store.findAll('event');
  }
});

In the console I see mirage returning succesfully data. When I do the following in the component JS…

console.log(this.get('events'));

… I’ll get an object.

I tried some things like…

let dataArr = this.get('events');
dataArr.map(item => {
    console.log(item.get('title'));
});

… which returns all titles, but fullcalender expects the complete JSON of all events.

I’m sure I’m overlooking something, but I don’t get it.


#2

Yup, you’re on the right track.

Once you start making calls to store.findAll you’re now working with Ember Data models, and not JSON payloads.

You’ll have to transform your models into json objects that fullCalendar can use.

didInsertElement() {
  let events = this.get('events');

  let dataForFullCalendar = events.map(event => {
    return {
      title: event.get('title'), // 'All Day Event',
      start: event.get('start'), // '2018-10-01',
      color: event.get('color')  // '#783f53'
    };
  });

  $('.jquerycal').fullCalendar({
      events: dataForFullCalendar
  });
}

Let me know if that works?


#3

Is this doc helpful for you ?


#4

I’m not sure, I recognized serializers as a way to transform existing JSON in a desired format, but not for transforming data coming from Ember store/model to transform into raw JSON. Looking at the Guide and Documentation gives no hints in this direction (at least for me). Could you provide a simple example how you would do it?


#5

Hi ryanto, yes that works, thank you – I was not able to wrap my head around it for hours… I always thought there must be a method to get the data directly instead of mapping it manually…


#6

@ryanto your suggested approach works fine, but if I’d use a third party component (namely ember-fullcalendar), I still struggle how to convert data coming from ember-data/mirage to plain json which fullcalendar only accepts…

{{full-calendar events=events weekNumbers=true}}

Any hints would be welcome, especially how to use serializers (maybe a topic for embermap as well…?) thx!


#7

I had the same problem and the documentation from ember-fullcalendar is a little sparse.

https://github.com/fossasia/open-event-frontend/blob/development/app/routes/events/view/scheduler.js

That route file from the above public repo helped me massage the model in my route into something that fullcalendar liked.


#8

You’ll need to transform for your event models into data for full calendar, just like we did when using the jQuery plugin.

Try using a computed property for that…

eventData: computed('events.[]', function() {
  let dataForFullCalendar = events.map(event => {
    return {
      title: event.get('title'), // 'All Day Event',
      start: event.get('start'), // '2018-10-01',
      color: event.get('color')  // '#783f53'
    };
  });

  return dataForFullCalendar;
})

Now in your template you can that data in handlebars.

{{full-calendar events=eventData weekNumbers=true}}

PS: I’m not sure what exactly the shape of your data should be, you’ll have to follow the ember-fullcalendar docs for that.


#9

@ryanto thank you, I already tried that but did not succed in getting it running. I understand that I need a controller for that (on the same route). I even setup one explicitly in the route.

route.js:

model(params) {
    return this.store.query('reservation', params);
},

setupController(controller, model) {
    controller.set('reservation', model);
}

controller.js:

init() {
    console.log(model); // undefined
},

eventData: computed('reservation.[]', function() {
  let dataForFullCalendar = reservation.map(event => {
    return {
      title: event.get('title'), // 'All Day Event',
      start: event.get('start'), // '2018-10-01',
      color: event.get('color')  // '#783f53'
    };
  });

  return dataForFullCalendar;
}),

#10

Looks good.

Quick question for you: Is your eventData computed property returning the right data that ember fullcalender needs to render?


#11

Unless you’ve removed some pieces from your example, the controller code is missing some things;

init() {
    console.log(this.get('reservation')); // this.get('reservation')
},

eventData: computed('reservation.[]', function() {
  let dataForFullCalendar = this.get('reservation').map(event => { // this.get('reservation')
    return {
      title: event.get('title'), 
      start: event.get('start'),
      color: event.get('color')
    };
  });

  return dataForFullCalendar;
}),

To explain this a bit more, since you override setupController() on the route and never call this._super(controller, model);, your model property on the controller is never set, therefore undefined.

I’m surprised you didn’t get linting errors for both console.log(model); and let dataForFullCalendar = reservation.map() as you didn’t “get” the properties from the this first.