ember.jsfullcalendarember-cliember-routerember-components

emberjs component doesn't rerender component to update fullcalendar


I am building a calendar app using emberjs and Jquery fullcalendar. The fullcalendar is rendered via emberjs component. However, when a new event is created via a form and the route refresh() method called, the component doesn't rerender or redraw itself. Therefore to see the new event on fullcalendar, I have to manually refresh the page. How can I get the component to rerender when a new event is created. I have tried with event route and template before using events/index route and template.

app/event/templates/index.hbs

 {{cal-event model=model event=model refreshModel='refreshModel'}}

app/routes/events/index.js

import Route from '@ember/routing/route':
export default Route.extend({
   model(){
     let model = this.get('store').findAll('event', {reload: true});
     return model;
   },

   actions: {
     refreshModel(data) {
       let e = data.get('start');
       let d = data.get('description');
       let f = data.get('finish');
       let event = this.get('store').createRecord('event', {description: d, start: e, finish: f})

       event.save().then((e) => {
         this.refresh(); 
         this.transitionTo("events")
       }, function(e) {
         console.log("event error", e)
       })   
     }
   }
 });

app/components/cal-event.js

 import Component from '@ember/component';
 import EmberObject, { computed, observer } from '@ember/object';
 export default Component.extend({
   event: '',

   didUpdateAttrs(data) {
     console.log('didUpdatedAttrs called', data);
   },

   didRender() {
     console.log('didRender');
   },

   didInsertElement() {
     this._super(...arguments);
     this.$().attr('contenteditable', true);
     return this.$("#calendar").fullCalendar({
       events: this.eventJSON(),
       defaultView: 'agendaWeek'
     });
   },

   eventJSON() {
     return this.get('model').map(function(event) {
      return event.get('toJSON');
     });
   },

   getnewEvent: computed('newEvent', function(){
     console.log('getnewEvent',  this.get('newEvent'));
   }),

   modelChanged: Ember.observer('model', function(){
     console.log("model changed!");
   }), 

  eventsDidChange: Ember.observer('model.[]', function() {
    this.$("#calendar").fullCalendar({
      events: this.eventJSON,
      defaultView: 'agendaWeek'
    });
  }),

   actions: {
     createEvent: function(param) {
       this.sendAction('refreshModel', param);
     }
   }
 });
Update.

I added didUpdateAttrs and didRender().

update 2

I got another suggestion from bendemboski through slack that I should try adding an observer on the model array as in Ember.observer('model.[]'). It didn't work, component is not rerendered and fullcalendar doesn't show the new event.

Thanks for helping.


Solution

  • Option1: Your current observer solution will work, mistake is eventsDidChange observer function you missed to call this.eventJSON()

    Option2.You want to draw the calendar again whenever there is change in model data, for that you can do rendering in didRender method. You don't need observer at all.

    Notes:

    1.Dont expect getnewEvent computed property will be called, it will be called only when you request for it thourgh get or in template. currently it looks its not returning the value. Remember computed property always should return the value. but this is not related to your problem.

    2.In events/index.js,

    this.refresh(); 
     this.transitionTo("events") 
    

    Both above will do the same thing, I think in your case you dont need to call both method, since your model hook is using the findAll so it will return live record array so it will be automatically be updated. due to that your cal-event component will call rerendering methods.