Vue-Full-Calendar refetch-events error - fullcalendar

I am having issues refreshing events when I add a new one. The event gets inserted into the database fine, but the call to
this.$refs.calendar.$emit('refetch-events')
Throws the following error:
[Vue warn]: Error in event handler for "refetch-events": "TypeError: $(...).fullCalendar is not a function"
Here is some more of the code to further demonstrate what I am trying to do:
<template>
<div>
<full-calendar ref="calendar" :event-sources="eventSources" #day-click="daySelected" #event-selected="eventSelected" :config="config"></full-calendar>
<!-- Modal Component -->
<b-modal ref="my_modal" title="New Appointment" #ok="submit" #shown="clearModalValues">
<form #submit.stop.prevent="submit">
<label>Client:</label>
<b-form-select v-model="selectedClient" :options="clientOptions" class='mb-3'></b-form-select>
<label>Service:</label>
<b-form-select multiple v-model="selectedService" :options="serviceOptions" class='mb-3'></b-form-select>
<label>Start time:</label>
<time-picker v-model="myTime"></time-picker>
<label>Notes:</label>
<b-form-input textarea v-model="notes" placeholder="Notes"></b-form-input>
</form>
</b-modal>
<!-- /Modal Component -->
</div>
</template>
<script>
export default {
props: {
staff:{
type: Number,
required: true
},
},
data() {
return {
myTime: new Date(),
selectedService: [null],
selectedClient: null,
selectedStartTime: new Date(),
notes: null,
serviceOptions: [],
clientOptions: [],
events: [],
config: {
timeFormat: 'h(:mm)',
eventClick: (event) => {
console.log('Event Clicked: '+event.title);
},
},
selected: {},
};
},
computed: {
eventSources() {
return [
{
events(start, end, timezone, callback) {
axios.get('/getEvents').then(response => {
callback(response.data)
})
}
}
]
}
},
mounted() {
this.myTime = new Date()
axios.get('/getClients').then(response => this.clientOptions = response.data);
axios.get('/getServices').then(response => this.serviceOptions = response.data);
},
methods: {
clearModalValues() {
this.selectedService = [null];
this.selectedClient = null;
this.selectedStartTime = new Date();
this.myTime = new Date();
this.notes = null;
},
submit(e) {
axios.post('/addEvent/',{'selectedService':this.selectedService,'selectedClient':this.selectedClient,'selectedStartTime':this.selectedStartTime,'notes':this.notes}).then(function(response){
//console.log(response.data);
new PNotify({
title: 'Success',
text: 'New event has been created',
icon: 'icon-checkmark3',
type: 'success'
});
this.selectedService = [null];
this.selectedClient = null;
this.selectedStartTime = new Date();
this.notes = null;
this.myTime = new Date();
// ******** I HAVE TRIED THESE CALLS AS PER DOCUMENTATION **********
//this.$refs.calendar.fireMethod('refetch-events')
//this.$refs.calendar.fullCalendar.$emit('refetch-events');
//this.$refs.calendar.$emit('refetch-events');
console.log(this.$refs.calendar);
}.bind(this));
},
eventSelected(event) {
console.log('Event Selected: '+event.title);
},
daySelected(date,event,view){
this.$refs.my_modal.show();
this.selectedStartTime = date.format("YYYY-MM-DD HH:mm:ss");
this.myTime = date.toDate();
},
},
};
</script>
According to the documentation it should be correct. I know its late and I have been at this for a couple hours so I might be overlooking something simple. Again this is vue-full-calendar and not regular full-calendar. I just need to call refetchEvents when I add the new events in the submit method. Thanks!

I have found the issue, thanks to Brock for the help. I had multiple versions of jquery running(the html template I was using was also calling it).

Related

How to get all checkbox props with React + ASP.net mvc

I am learning React and ASP.net( not core).
I try to create a small project for practice.
I have a number of checkboxes and a submit button.
The idea is when I click on the button I want to create a Jason that will contain a list of the checkboxes text and their states (check \uncheck).
That Jason I want to send to the server.
I mange to create the components and the relevant events.
But fail to create the following
1) Get the state of the checkbox from the submit component and create a Jason out of it.
2) Send that Jason to the server side (ASP.net).
I try to flow the tutorial but didn’t get it, I tried to find solution on the internet but with no lack.
If someone can show me how to do it – or give me some direction that will help
Thanks
the jsk:
var data = [
{ Id: 1, ActionItem: "Action1" },
{ Id: 2, ActionItem: "Action2" },
{ Id: 3, ActionItem: "Action3" }
];
var Checkbox = React.createClass({
getInitialState: function() {
return {
isChecked: false
};
},
toggleChange: function() {
this.setState({
isChecked: !this.state.isChecked
},
function() {
console.log(this.state);
}.bind(this));
},
render: function() {
return (
<label>
<input type="checkbox"
checked={this.state.isChecked}
onChange={this.toggleChange} />{this.props.chkboxlabel}<br />
</label>
);
}
});
var ActionBox = React.createClass({
render: function() {
return (
<div className="actionBox">
<h1>Select Action </h1>
<CheckboxList data={this.props.data} />
<SubmitForm/>
</div>
);
}
});
var CheckboxList = React.createClass({
render: function() {
var actionNodes = this.props.data.map(function(action) {
return (
<Checkbox chkboxlabel={action.ActionItem} key={action.id}>
{action.ActionItem}
</Checkbox>
);
});
return (
<form className="actionList">{actionNodes}
</form>
);
}
});
var SubmitForm = React.createClass({
handleSubmit: function(e) {
//??
},
render: function() {
return (
<form className="actionForm" onSubmit={this.handleSubmit}>
<input type="submit" value="Run" />
</form>
);
}
});
ReactDOM.render(
<ActionBox data={data} />,
document.getElementById('content')
);
I found a solution that works I don’t think it’s the best way but maybe it will help other.
I loop thought the element to get the value- I believe there is a better way of doing it with react.
var data = [
{ Label: "Action 1", IsChecked: false, Name: "a1" },
{ Label: "Action 2", IsChecked: false, Name: "a2" },
{ Label: "Action 3", IsChecked: false, Name: "a3" }
];
handleCommentSubmit: function () {
var data = new FormData();
var inputs = document.getElementsByName('mycheckbox');
for (var i = 0; i < inputs.length; i++) {
var name = inputs.item(i).value;
var ischecked = inputs.item(i).checked;
data.append(name, ischecked);
}
var xhr = new XMLHttpRequest();
xhr.open('post', this.props.submitUrl, true);
xhr.send(data);
},

fullcalendar - multiple sources to turn off and on

I've a calendar that I want to list various types of event on and enable a checkbox filter to show/hide those kind of events.
Is there a way to say on this action, ONLY load from 1 data-source AND remember that URL on month next/prev links?
I've started using eventSources, but it loads them all, rather than the one(s) I want.. Here's what I have.
var fcSources = {
all: {
url: tournament_url + '/getCalendar/?typefilter=[1,2]'
},
type1: {
url: tournament_url + '/getCalendar/?typefilter=[1]'
},
type2: {
url: tournament_url + '/getCalendar/?typefilter=[2]'
}
};
These URLS all provide a json string of events, based on the types prrovided.
Here's my calendar:
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek'
},
firstDay: 1, // Monday = 1
defaultDate: new Date(), // Now
editable: true,
eventSources: [ fcSources.all ],
events: fcSources.all,
nextDayThreshold: '00:00:00',
... etc etc
Above my calendar I have this:
input type="checkbox" name="event_filter[]" value="type1" /> Type 1
input type="checkbox" name="event_filter[]" value="type2" /> Type 2
And finally , two Jquery fucntions.. one to get all the filters:
function getFilters(getName) {
var filters = [];
var checked = [];
$("input[name='"+getName+"[]']").each(function () {
filters.push( $(this).val() );
});
$("input[name='"+getName+"[]']:checked").each(function () {
checked.push( $(this).val() );
});
return [filters, checked];
}
and the last to load them:
$(".event_filter").on('click', function() {
var doFilters = getFilters('event_filter');
$('#calendar').fullCalendar( 'removeEvents' );
if (doFilters[0] === doFilters[1]) {
$('#calendar').fullCalendar( 'addEventSource', fcSources.all );
} else {
$.each(doFilters[1], function(myFilter, myVal) {
console.log(myVal);
$('#calendar').fullCalendar( 'addEventSource', fcSources.myVal );
});
}
// $('#calendar').fullCalendar( 'refetchEvents' );
});
Since the sources are all the same place and just different data on the URL, this approach could meet your needs. In the demo it just alerts the URL that is being tried but doesn't actually supply any data...
https://jsfiddle.net/gzbrc2h6/1/
var tournament_url = 'https://www.example.com/'
$('#calendar').fullCalendar({
events: {
url: tournament_url + '/getCalendar/',
data: function() {
var vals = [];
// Are the [ and ] needed in the url? If not, remove them here
// This could (should!) also be set to all input[name='event_filter[]'] val's instead of hard-coded...
var filterVal = '[1,2]';
$('input[name="event_filter[]"]:checked').each(function() {
vals.push($(this).val());
});
if (vals.length) {
filterVal = '[' + vals.join(',') + ']' // Are the [ and ] needed in the url? If not, remove here too
}
return {
typefilter: filterVal
};
},
beforeSend: function(jqXHR, settings) {
alert(unescape(settings.url));
}
}
});
// when they change the checkboxes, refresh calendar
$('input[name="event_filter[]"]').on('change', function() {
$('#calendar').fullCalendar('refetchEvents');
});
Try this!
$('#calendar').fullCalendar({
events: function( start, end, timezone, callback ) {
var checked = [];
$("input[name='event_filter[]']:checked").each(function () {
checked.push( $(this).val() );
});
var tournament_url = 'https://www.example.com';
$.ajax({
url: tournament_url + '/getCalendar/',
data: {typefilter: '['+checked.join(',')+']'},
success: function(events) {
callback(events);
}
});
}
});
$('input[name="event_filter[]"]').on('change', function() {
$('#calendar').fullCalendar('refetchEvents');
});
This works for me.

Update function returns an error

This code returns an "Error: $scope.todoItems.update is not a function"
(in markDone function)
As I can see in console, $scope.todoItems has functions like save(), remove() but not an update() function, but as I can see here I writing it right.
Is something that I doing is wrong? More information would be helpful?
TodoItems = new Mongo.Collection('todoItems');
if(Meteor.isClient){
angular.module('todo_am', ['angular-meteor']);
angular.module('todo_am').controller('OutputListCtrl', ['$scope', '$meteor',
function($scope, $meteor){
$scope.todoItems = $meteor.collection(TodoItems);
$scope.remove = function(todoItem){
$scope.todoItems.remove(todoItem);
};
$scope.saveCustom = function(todoItem){
todoItem.isRead = false;
$scope.todoItems.save(todoItem);
};
$scope.markDone = function(todoItem){
console.log('>>> 4', todoItem);
console.log('>>> 5', $scope.todoItems);
$scope.todoItems.update(todoItem._id, { $set: { isRead: true }}); // <<<<<<<<< This line returns error
};
$scope.markUndone = function(todoItem){
todoItem.isRead = true;
$scope.todoItems.update(todoItem);
};
}]);
}
------------------------------ UPDATE --------------------------------
This is working:
if(Meteor.isClient){
angular.module('todo_am', ['angular-meteor']);
angular.module('todo_am').controller('OutputListCtrl', ['$scope', '$meteor',
function($scope, $meteor){
$scope.todoItems = $meteor.collection(TodoItems);
$scope.remove = function(todoItem){
$scope.todoItems.remove(todoItem);
};
$scope.saveCustom = function(todoItem){
todoItem.isRead = false;
$scope.todoItems.save(todoItem);
};
$scope.markDone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: true }});
};
$scope.markUndone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: false }});
};
}]);
}
------------------------------ UPDATE2 --------------------------------
This is whole code. I do not know if it's a right solution or not but it works.
Is there any example for update exists record in DB?
$ meteor --version
Meteor 1.1.0.2
As I can see in .meteor/versions file:
angular:angular#1.3.15_1
urigo:angular#0.8.6
index.html
<body ng-app="todo_am">
<div ng-controller="OutputListCtrl">
<div ng-include="'output-list.ng.html'"></div>
<div ng-include="'insert-new-form.ng.html'"></div>
</div>
</body>
index.ng.html
<p>Nothing</p>
insert-new-form.ng.html
<div>
<input type="text" ng-model="newTodoItem.text" />
<button ng-click="saveCustom(newTodoItem); newTodoItem='';" >Add New</button>
</div>
output-list.ng.html
<div>
<ul>
<li ng-repeat="todoItem in todoItems">
<p>
{{ todoItem.text }}
<span ng-switch on="todoItem.isRead">
<span ng-switch-when="true">
<button ng-click="markUndone(todoItem)">Mark Undone</button>
</span>
<span ng-switch-default>
<button ng-click="markDone(todoItem)">Mark Done</button>
</span>
</span>
<button ng-click="remove(todoItem)">X</button>
</p>
</li>
</ul>
</div>
app.js
TodoItems = new Mongo.Collection('todoItems');
if(Meteor.isClient){
angular.module('todo_am', ['angular-meteor']);
angular.module('todo_am').controller('OutputListCtrl', ['$scope', '$meteor',
function($scope, $meteor){
$scope.todoItems = $meteor.collection(TodoItems);
$scope.remove = function(todoItem){
$scope.todoItems.remove(todoItem);
};
$scope.saveCustom = function(todoItem){
todoItem.isRead = false;
$scope.todoItems.save(todoItem);
};
$scope.markDone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: true }});
};
$scope.markUndone = function(todoItem){
TodoItems.update({ _id: todoItem._id }, { $set: { isRead: false }});
};
}]);
}
if(Meteor.isServer){
Meteor.startup(function(){
/**
* If DB is empty, add some todoItems just for DEV purposes
*/
if (TodoItems.find().count() === 0) {
var todoItems = [
{
'text': 'First todo first todo first todo first todo first todo first todo first todo first todo first todo',
'isRead': true,
'userPosted': 'Vasia'
},
{
'text': 'Second todo item',
'isRead': false,
'userPosted': 'Fedia'
},
{
'text': 'Third todo item',
'isRead': true,
'userPosted': 'Vasia'
}
];
for (var i = 0; i < todoItems.length; i++)
TodoItems.insert({text: todoItems[i].text, isRead: todoItems[i].isRead});
}
});
}
That doesn't look like $scope.todoItems is a Meteor collection. If you look through the documentation you linked (http://docs.meteor.com/#/full/mongo_collection) - there's no reference to Meteor's Mongo Collections having a "save" method.
It looks like you're using an "Angular Meteor Collection" - http://angularjs.meteor.com/api/AngularMeteorCollection
In which case a simple call to ".save" should do it. Perhaps something like this:
$scope.markDone = function(todoItem){
todoItem.isRead = true;
$scope.todoItems.save(todoItem);
};

Meteor.js collection aggregate returning undefined is not a function

I am trying to make collection aggregate in my Meteor.js app as shown below, yet each time I call my server logSummary method I get the following error. Can someone please tell me what I am doing wrong / how to resolve this error? Thanks.
Note: I am using Meteor-aggregate package
TypeError: undefined is not a function
at Object.Template.detailedreport.helpers.myCollection (http://localhost:3000/client/views/report.js?
Code:
Template.detailedreport.rendered = function() {
Session.set("dreport_customer", "");
Session.set("dreport_project", "");
Session.set("dreport_startDate", new Date());
Session.set("dreport_endDate", new Date());
$('.set-start-date').datetimepicker({
pickTime: false,
defaultDate: new Date()
});
$('.set-end-date').datetimepicker({
pickTime: false,
defaultDate: new Date()
});
$('.set-start-date').on("dp.change",function (e) {
Session.set("dreport_startDate", $('.set-start-date').data('DateTimePicker').getDate().toLocaleString());
});
$('.set-end-date').on("dp.change",function (e) {
Session.set("dreport_endDate", $('.set-end-date').data('DateTimePicker').getDate().toLocaleString());
});
};
Template.detailedreport.helpers({
customerslist: function() {
return Customers.find({}, {sort:{name: -1}});
},
projectslist: function() {
return Projects.find({customerid: Session.get("dreport_customer")}, {sort:{title: -1}});
},
myCollection: function () {
var now = Session.get("dreport_startDate");
var then = Session.get("dreport_endDate");
var custID = Session.get("dreport_customer");
var projID = Session.get("dreport_project");
Meteor.call('logSummary', now, then, projID, custID, function(error, data){
if(error)
return alert(error.reason);
return data;
});
},
settings: function () {
return {
rowsPerPage: 10,
showFilter: true,
showColumnToggles: false,
fields: [
{ key: '0._id.day', label: 'Day' },
{ key: '0.totalhours', label: 'Hours Spent'}
]
};
}
});
Template.detailedreport.events({
'submit form': function(e) {
e.preventDefault();
Session.set('dreport_endDate', $('.set-end-date').data('DateTimePicker').getDate().toLocaleString());
Session.set('dreport_startDate', $('.set-start-date').data('DateTimePicker').getDate().toLocaleString());
Session.set('dreport_project', $(e.target).find('[name=project]').val());
Session.set('dreport_customer', $(e.target).find('[name=customer]').val());
},
'change #customer': function(e){
Session.set("dreport_project", "");
Session.set("dreport_customer", e.currentTarget.value);
},
'change #project': function(e){
Session.set("dreport_project", e.currentTarget.value);
}
});
Template:
<div>
{{> reactiveTable class="table table-bordered table-hover" collection=myCollection settings=settings}}
</div>
Server:
Meteor.methods({
logSummary: function(startDate, endDate, projid, custid){
var pipeline = [
{ $match: { date: { $gte: new Date(startDate), $lte: new Date(endDate) },
projectid: projid,
customerid: custid
}
},
{ $group: {
_id: {
"projectid": "$projectid",
"day": { "$dayOfMonth": "$date" },
"month": { "$month": "$date" },
"year": { "$year": "$date" }
},
totalhours: {"$sum": "$hours"}
}}
];
return ProjectLog.aggregate(pipeline);;
}
});
Looking at the ReactiveTable documentation, it looks like you need to do something like:
Template.myTemplate.helpers({
myCollection: function () {
return myCollection;
}
});
Where myCollection is the name of a Mongo/Meteor collection (e.g. BlogPosts) which you defined with e.g. BlogPosts = new Mongo.Collection('blogPosts');
The reason you're getting undefined is not a function is that you are calling a Meteor method inside a template helper. The call is asynchronous so the return value is undefined. Now you are passing undefined to ReactiveTable. ReactiveTable will be trying to call something like myCollection.find() which is essentially undefined.find() and will therefore throw the error you're seeing.
Later on the Meteor call will finish and the data value will be lost because the function has already returned.
You can call Meteor.call inside the onCreated function like so:
Template.myTemplate.onCreated(function () {
Meteor.call('myFunction', 'my', 'params', function (err, result) {
if (err) {
// do something about the error
} else {
Session.set('myData',result);
}
});
});
Template.myTemplate.helpers({
myData: function () {
Session.get('myData')
}
});
This won't fix the issue with ReactiveTable, however.
If the collection you're trying to display is only used for this single page, you could put the aggregation inside the publish function so that minimongo contains only the documents that match the aggregation and therefore the correct documents will appear in your ReactiveTable.

Meteor.js calling a template.helpers function vs global variable

I am using Reactive-table to display paginated data in my meteor.js app as shown below, yet data displayed in Reactive-table is dependent on on specific user event (Selecting client, project, date range and clicking on the submit button). So I was wondering if it is possible to trigger template.helpers >> myCollection function from the 'submit form' event? OR is it better to define a global variable to store data returned from user query based on the user (client, project, date range selection) then make this global variable the return from the myCollection function?
I have tried researching how to call .helpers function from an template.events event but couldn't find any information. So any help on which approach is better and if calling the .events function is better then how to do that, will be highly appreciated. Thanks.
Below is the code I have in my app:
Template.detailedreport.rendered = function() {
Session.set("dreport_customer", "");
Session.set("dreport_project", "");
Session.set("dreport_startDate", new Date());
Session.set("dreport_endDate", new Date());
$('.set-start-date').datetimepicker({
pickTime: false,
defaultDate: new Date()
});
$('.set-end-date').datetimepicker({
pickTime: false,
defaultDate: new Date()
});
$('.set-start-date').on("dp.change",function (e) {
Session.set("dreport_startDate", $('.set-start-date').data('DateTimePicker').getDate().toLocaleString());
});
$('.set-end-date').on("dp.change",function (e) {
Session.set("dreport_endDate", $('.set-end-date').data('DateTimePicker').getDate().toLocaleString());
});
};
Template.detailedreport.helpers({
customerslist: function() {
return Customers.find({}, {sort:{name: -1}});
},
projectslist: function() {
return Projects.find({customerid: Session.get("dreport_customer")}, {sort:{title: -1}});
},
myCollection: function () {
var now = Session.get("dreport_startDate");
var then = Session.get("dreport_endDate");
var custID = Session.get("dreport_customer");
var projID = Session.get("dreport_project");
Meteor.call('logSummary', now, then, projID, custID, function(error, data){
if(error)
return alert(error.reason);
return data;
});
}
},
settings: function () {
return {
rowsPerPage: 10,
showFilter: true,
showColumnToggles: false,
fields: [
{ key: '0._id.day', label: 'Day' },
{ key: '0.totalhours', label: 'Hours Spent'}
]
};
}
});
Template.detailedreport.events({
'submit form': function(e) {
e.preventDefault();
var now = $('.set-start-date').data('DateTimePicker').getDate().toLocaleString();
var then = $('.set-end-date').data('DateTimePicker').getDate().toLocaleString();
var custID = $(e.target).find('[name=customer]').val();
var projID = $(e.target).find('[name=project]').val();
//Here is the problem as I am not sure how to refresh myCollection function in .helpers
},
'change #customer': function(e){
Session.set("dreport_project", "");
Session.set("dreport_customer", e.currentTarget.value);
},
'change #project': function(e){
Session.set("dreport_project", e.currentTarget.value);
}
});
Template:
<div>
{{> reactiveTable class="table table-bordered table-hover" collection=myCollection settings=settings}}
</div>
Server:
Meteor.methods({
logSummary: function(startDate, endDate, projid, custid){
//Left without filtering based on date, proj, cust for testing only...
return Storylog.find({});
}
});
Template helpers are reactive, meaning that they will be recomputed if their dependencies change. So all you need to do is update their dependencies and then the myCollection helper will be recomputed.
Replace your comment // Here is the problem... with:
Session.set('dreport_endDate', then);
Session.set('dreport_startDate', now);
Session.set('dreport_project', projID);
Session.set('dreport_customer', custID);

Resources