问题
I'm still struggling to get a calendar to re-render when data changes using meteor blaze. I have put in place an observerChanges function that is firing happily when added, removed or changed are triggered, but I have NO idea how to actually make the calendar update its state.
The handler code is
Meteor.subscribe("reqEvents");
allReqsCursor = Requests.find();
var handle = allReqsCursor.observeChanges({
added: function (id, user) {
console.log("Request added");
},
removed: function () {
console.log("Request removed");
},
changed: function() {
console.log("Request changed");
// $('#calendar').fullCalendar().today();
}
});
And the render function itself is
Template.packLayout.rendered = function(){
$('#calendar').fullCalendar({
//dayClick:function( date, allDay, jsEvent, view ) {
// Requests.insert({title:'Request',start:date,end:date,color:'red',className:'todo'});
// Session.set('lastMod',new Date());
//},
eventClick:function(reqEvent,jsEvent,view){
Session.set('editingReqEvent',reqEvent.id);
Session.set('showEditEvent',true);
},
eventDrop:function(reqEvent){
Requests.update(reqEvent.id, {$set: {start:reqEvent.start,end:reqEvent.end}});
Session.set('lastMod',new Date());
},
events: function(start, end, callback) {
var events = [];
reqEvents = Requests.find();
reqEvents.forEach(function(evt){
event = {id:evt._id,title:evt.title,start:evt.start,end:evt.end,color:evt.color};
events.push(event);
})
callback(events);
},
editable:true,
weekMode: 'liquid',
});
};
How do I hook these together? I've tried a few things (as per the commented out code) but it either blows up or renders the calendar twice.
Is this even the best way? Should I put a deps.autorun in somewhere else?? If so where?
回答1:
FullCalendar should be instantiated only once in Template.packLayout.rendered function. I recommend to get reference of fullCalendar instance :
var calendar = null
Template.packLayout.rendered = function(){
// only once !
calendar = $('#calendar').fullCalendar({...});
}
Template.packLayout.helpers ({
data:function(){
allReqsCursor = Requests.find();
var handle = allReqsCursor.observeChanges({
added: function (id, user) {
console.log("Request added");
},
removed: function () {
console.log("Request removed");
},
changed: function() {
console.log("Request changed");
if(calendar){
calendar.today();
}
}
});
return allReqsCursor;
}
})
Template.packLayout.helpers.data is being rerun every time Requests collection is updated. Something like above code should help you.
Instead using Template.packLayout.helpers.data function you can use:
Deps.autorun(function(){
allReqsCursor = Requests.find();
// update calendar
})
回答2:
Use the internal calendar functions to re-render the calendar when things change:
Deps.autorun(function () {
if (Session.equals('calendarTemplateRendered', false) ||
!calendarSubs.ready() ||
typeof Calendar === 'undefined') {
console.log('exiting because there is no objects to process');
return;
}
console.log('trying to autorun');
var entries = Calendar.find().fetch(),
$calendar = $('#calendar');
$calendar.fullCalendar('removeEvents');
$calendar.fullCalendar('addEventSource', entries);
$calendar.fullCalendar('rerenderEvents');
}
Blaze does the rest for you. Dunno how efficient this is but it works pretty nicely for me. Now you can just manipulate the subscription 'Calendar' "insert, del etc' and the calendar will work properly.
来源:https://stackoverflow.com/questions/23453415/making-bootstrap-calendar-render-when-data-change-in-meteor