FullCalendar Events lose user data after renderEvent or updateEvent - javascript

I have event objects I load into fullcalendar. Each event has a custom resources array field attached showing who the events are for. Loads fine. User can click on the event and eventClick gives me the event with the resources. I open a dialog to edit. After saving changes to the db, I want to update the calendar using updateEvent. The object I use to update contains the full resources array and all appears to update fine.
Here's the problem: Now when I click on the same event to edit again, the event returned by eventClick has the resources array length set to 0. i.e. all the resources elements are missing.
Thought maybe I wasn't updating with the 'original object' so tried removeEvents followed by renderEvent but get the exact same behavior.
What am I missing?
btw, using fullCalendar 1.6. I can just reload the calendar and it's fine, but I don't want to 'cause it flickers and means unnecessary bytes over the wire.
update
So if I use appointment.resources = angular.copy(appointment.resources) then everything works. I'm not clear on why though. Is it because the attached resources were from an angular $resource and when that refreshed the reference to the previous objects point nowhere?

I think it could be a reference problem.
When you create a fullCalendar event, it wraps the object to a new one.
So, if you do something like:
var myEvent = {id: 1, title: "MyTitle", resources:[1,2,3], start:moment()};
$.('#calendar').fullCalendar('renderEvent', myEvent);
It create another object, with some specific properties like backUps, specific methods, etc... You can access this object with:
var fcEvent = $.('#calendar').fullCalendar('clientEvents', myEvent.id);
But now:
fcEvent.resources != myEvent.resources
Anyway, is difficult to know exactly what's the problem without a piece of code. Is possible to create a Plunker?
You can use my public Skeleton for ui-calendar

Related

Cytoscape event cxttap called multiple times

I am trying to create a network workflow with Cytoscape and AngularJS 1.6
After creating two nodes, user is able to create an edge between them. For this I am using cy.on('cxttap') cytoscape function to detect right clicks on both the nodes and then insert a new edge.
This works fine. Until I added a new view, where the user can see saved workflows from the database. The problem is, if I open the Viewing tab and then go back to creation tab, the cy.on('cxttap') function is called twice, and two edges are inserted on the cytoscape canvas, but only one entry is made in my scope variable. I used to have the same factory for both the views but now I am using different angular factories for each.
If I open switch between these tabs multiple times, the number of times I open the viewing tab, is the number of times the function is called, hence more the number of lines.
Here (https://jsfiddle.net/y47kwpg7/4/) is the snippet with the code for both my views with their controllers. "Creation View" --> "MlalTextWorkflowGeneratorCtrl" and "Viewing View" --> "MlalTextWorkflowViewerCtrl".
(Please forgive me, I don't know how to make it work in a single file)
The factory I have here is for the cytoscape canvas, and have a similar one for another view, but with a different id selection.
Thank you for your help!
You either need to
(1) remove old listeners if you're re-using an instance, or
(2) create a new instance each time you create a new view.
#maxkfranz 's answer guided me to do a little more debugging and finally I found out the problem.
The problem was I had some listener functions that I called from my controller in order to detect events on the cytoscape nodes. And the listeners to fire were stored in a a variable workflowGraph.listeners. you can see the old code []1. The problem was this variable was not emptied anytime my controller was reloaded, because I was calling the listeners from my controller, they were being added to this variable once again. So, one listener had multiple functions to call.
The method I used to solve this was to create a new "listener" type function I had earlier for cytoscape events, which I would call everytime my controller is loaded, to empty the listeners variable for my cytoscape factory.
In cytoscape factory
workflowGraph.reinitialize = function () {
workflowGraph.listeners = {};
};
In controller
workflowCreation is the name of the factory
workflowCreation.reinitialize();
This would simply empty the listeners variable from the factory.
Remember to call this in your controller after cytoscape initialisation and before calling any other listener functions
Hope this helps someone.

Fullcalendar can't access html5 data attribute in drop, only on Firefox

I have fullcalendar setup to grab the html5 data attribute "event" from external events. For reasons unnecessary to get into, I am needing to access that data in the drop event handler in fullcalendar, but when I use var foo = $(this).data(event);, it seems to stop the script at that point, but only in Firefox, and no errors show in the console.
Here is a jsfiddle showing it. For some reason, the calendar isn't working right, but that is not my problem. The problem shows itself when you drop the event anywhere on the calendar. In chrome, you will see a total of 3 alert boxes. In Firefox, only two.
You are using the wrong method here.
.data() is for storing arbitrary data,
Store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.
[…]
The .data() method allows us to attach data of any type to DOM elements
This "data store" has little to do with HTML5 data attributes.
To read those, you should simply use: $(this).attr('data-event')

KnockoutJS bindings not working

Ok getting frustrated on this one.... Using knockoutJS to do some visual interaction stuff.
What I have is a button that is going to make an AJAX call to validate some data. That call sends back a CanProceed property as well as an object that represents other view settings. The code works when I set CanProceed(true) this turns on a DIV that has more DIVs inside it, each of those visibility properties are bound to a Permissions.AllowXXX that is set from the server.
See the fiddle for an example
http://jsfiddle.net/RcCAx/
What I want to have happen is when I get the Permissions from the server I should be able to tell knockout about the object and have the page UI update but its not working. If I declare the observable first (like with the CanProceed property) it works, but if I try and use the ko.mapping.fromJS(serverdataobject) here its not updating stuff that was bound to it earlier.
Help......
See updated fiddle for a solution. The key here is to have Permissions be an observable

jquery full calendar: initialize an array from source every time new events are fetched

I want to initialize a global array of events everytime new events are fetched from the database. T explain some more, i want my events in a global array on the client side so that i can filter events without an ajax call. For example, if i have events, and each event has a country associated with it, i have multiple select box where you can select one or more country. I use the clientEvents functions to filter events taht match the criteria but the problem comes when the user starts reducing the filters. Then i need the events that i have already filtered out and for that i dont want to make an ajax call. So my approach is to have a global array of events, and when the user clears the filters, i just simply refectch all the events from that array.
Now the problem is , where to initialize that array?? if i do it in eventAfterRender, it changes in when the filtered events are being rendered, if i do it in viewDisplay, it isnt even initialized, i dont know why, i read somewhere that viewDisplay gets called before the events are rendered if you are using json feed. So i am stuck.... Please any help would be great.
You could use a function as the feed:
http://arshaw.com/fullcalendar/docs/event_data/events_function/
Then you can load the events from wherever you want and combine your array with data from a json source. It is up to your function to decide where to grab the data.
I suppose you will have to call the refetchEvents method after some external factors like choosing another country is done (your function providing events should take the selection of countries into concideration when generating the events to display).

How to add an item to an ExtJS GridPanel without firing selectionchanged event

I've got an ExtJS interface that addresses a problem I'm sure tons of people have had before. I have a service that exposes a list of items, and I need to show that list in a GridPanel. I have this part working. When I click one of the items, I handle the selectionchange event in the GridPanel's SelectionModel, and use it to load details of the resource from another REST call.
Now, I want to be able to add a new item. This seems like it should be simple, but I want to add the item to the GridPanel and at the same time clear the "detail" fields so the user can enter new details and save a complete item. I have an Add button, which creates a Prompt to input an item name.
Now, I add this item to the GridPanel's backing data store (a JsonStore if that matters) and use getSelectionModel().selectLastRow() to highlight it. Of course, this fires off the selectionchange event, which wants to load the details of the (non-existent) item. I've tried using .purgeListeners(), making the `selectLastRow() call, then restoring the selectionchange listener, but for some reason the changed event still fires off -- I don't actually have any symptoms in the UI, but I can see in Firebug that it's making a (failed) GET call for the item details.
I'd like to stop this from happening, and I feel like this should be a common / easy problem, but I haven't been able to find a solution. What's the right way to add a new item to the GridPanel without having your code try to "look up" the item before you save it?
ETA: A commenter pointed out that there's a phantom property on Record objects, which sounds like exactly what a want. However, when I load my item list as
STORE = new Ext.data.JsonStore({
autoLoad: true,
url: 'items'
method: 'GET',
storeId: 'store',
root: 'list',
remoteSort: false,
fields: ['name']
});
all the records in the list, as soon as I load them, are marked phantom. Does phantom not work with JsonStore? Should I go about this another way?
ETA Again: OK, found it. I wasn't setting the idProperty property on my JsonStore constructor, which meant that the Records didn't have an id, which meant that they were always phantom. Now my new record shows phantom while ones that are already in the DB do not. Woo-hoo!
I would prefer to do this without messing with the event chain or handlers that I have already setup.
One easy way seems along the lines of - "somehow figure out in the selectionchange listener whether record that was selected is a persistent one or not (yet)"
The "figuring out" part can be achieved by checking record.phantom as suggested by Kevin in comments below

Categories