Adding events as json array in FullCalendar? - arrays

I have a web page (written with PHP/Zend) with a full calendar component which is driven by a combo-box. This combo-box is used to switch from one calendar to another. Each time the user changes the value of the combo-box, we fetch the events in the database and "json" them as an array to the JavaScript. Then, we erase all events from the present calendar (empty current calendar) and add the newest event... but it does not work.
As the query to obtain all the events between two dates is long to execute we want to make it once for each calendar (each time user change the value of the combo-box).
My JavaScript code where $('#planning').val() is the combo-box value. The result variable contains a JSON array which has been validate.
<script type="text/javascript">
$(document).ready(function()
{
$("#planning").change(function() {
$.post(
'/Jerome/public/index/update-calendar',
{ planning: $('#planning').val() },
function(result) {
$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar(result); //not working
$('#calendar').fullCalendar( 'addEventSource',result);//not working
$('#calendar').fullCalendar( 'refetchEvents' ); //anything change
$('#calendar').fullCalendar( 'rerenderEvents' ); //anything change
});
});
});
</script>

It looks to me like your issue is when you're trying to load the new events. Full Calendar wouldn't know what to do with your JSON object try replacing...
$('#calendar').fullCalendar(result);
With..
$('#calendar').fullCalendar( 'addEventSource', result )
Here is a link to documentation.
I hope this helps!

Related

How to Create GA Events for Each Member of an Array in GTM

In our data layer, we have an array of add-ons for our products
Add-ons: [
{code: 'wheels', selection: 'alloy'),
{code: 'finish', selection: 'pearl'}
],
Unfortunately they are not the same for each product and are not returned in the same order.
We would like to create GA events for each add-on selected, using the code and selection in the array as the event Action and Label. So we need to loop through the array and create a new event for each item, and use the elements of the array in the event.
I created a GTM variable that pulls in the array (that works fine), but now I need to fire the event tracking. I've been working with forEach
<script>
{{addon-list}}.forEach(function(arrayItem) {
dataLayer.push({
'event': 'GAEvent',
'eventCategory': 'AddOn',
'eventAction': {{addon-list}}.code,
'eventLabel': {{addon-list}}.selection,
'nonInteraction': 1
})
});
</script>
While it fires one event, it is undefined for the Action and Label. Any ideas? This seems like a handy thing so I'm sure someone has done / is doing it.
Through a lot of iteration, I managed to arrive at a solution.
First, the GTM variable that pulls in the array needs to be version 1 because of how the data gets handled.
Then the script is:
<script>
{{addon-list}}.forEach(createEvent);
function createEvent (addon) {
dataLayer.push({
'event': 'GAEvent',
'eventCategory': 'AddOn',
'eventAction': addon.code,
'eventLabel': addon.selection,
'nonInteraction': 1
})
};
</script>
By declaring the value of addon and using it in the variables to pull in the elements of the array, it worked.

Facebook Pixel Custom Dimensions Only Appearing on First Pageview

We have a single page Angular app with the Facebook pixel that is injected via GTM. In the first injection, we pass the following:
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '<OUR ID>'); // Insert your pixel ID here.
</script>
Note, there is no pageview event. We then push a custom "virtual pageview" event to the GTM datalayer that leads to a tag that sends the pageview to Google Analytics (working fine), and triggers an injection of the following code as well:
<script>
fbq('track', 'PageView', {
dim1:{{dim 1 macro}},
dim2:{{dim 2 macro}},
dim3:{{dim 2 macro}}
});
</script>
On EACH pageview, the above fbq is appended to the DOM with the proper dimensions populated (by viewing the source of the page).
On the FIRST pageview HIT to Facebook, the dimensions are present in the call (by viewing the network tab), but on the SUBSEQUENT pageviews, a hit is sent to Facebook, BUT no dimensions are sent, even though they are present in the code appended to the DOM.
For the most part, these dimensions do not change hit to hit, but could change based on the actions the user does throughout their sessions.
Any thoughts as to why the subsequent hits DO NOT include the custom dimensions?
You try to update a payload every time a history change happens in an Angular app and execute the fb code again with the updated payload?
I would implement a datalayer on your front-end:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'virtualPageView',
pagePath: '/newPath', //update this path from your angular route,
//or use GTMs built in history-change trigger
//and a variable that gets the URL fragment
//to update your pageview's path variable.
customDimenson1: 'value1',
customDimenson2: 'value2',
customDimenson3: 'value3'
});
</script>
Create a trigger of the type Custom Event with the name virtualPageView.
Create 4 variables of the type Data Layer Variable, for pagePath, customDimension1-3.
Create your Custom HTML Tag which contains your fbq event:
<script>
fbq('track', 'PageView', {
dim1:{{customDimenson1}},
dim2:{{customDimenson2}},
dim3:{{customDimenson3}}
});
</script>
Create another Custom HTML Tag that fires on the built-in trigger All Pages, as it only needs to be executed once for your Single Page Application, with your base code:
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '<OUR ID>'); // Insert your pixel ID here.
</script>
I had problems with SPA for updated variables. Sometimes it's a race condition, sometimes it's bugs in GTM or your code. You can also try to delay the execution by using a 100ms timer (bad advice).
Received feedback from the official Facebook team, it seems that this is by design. On any subsequent call with a Pageview event, no custom data will be sent in the payload.

Refresh data on change in scope variable

I'm using AngularJS for an external web project.
I'm stuck with the update interval of the page as the JSON data I get is from the html div from inside the page, JSON data is being sent from policy.
I'm using
$scope.json_data = angular.element(document).find('#idofthejsondiv').html();
The div gets different JSON data for every 'x' seconds.
How can I update the page on the change in the divs value?
try this:
$scope.$watch (
function () {
return angular.element(document).find('#idofthejsondiv').html();
},
function (newValue) {
console.log (newValue);
// do stuff with the new value...
}
);
but it has to be mentioned that this doesn't seem like a appropriate structure of your app. the data in the div has to be changed somewhere somehow by some service. the better approach would be to intercept this service whenever it puts the changes to the div and do whatever you want with that new content

angular calendar detect month change event

I have the following issue while using the angular ui calendar component, as when the page loads I have like 60 records (full of information) I pull off the DB and this makes the reloading really awfull.
I realize I could detect when the user switches from one month to another and so load only the records corresponding to that month (According to the view).
Is there any angular ui calendar event to detect or be aware of this ?. Thankx !.
This is pulled from docs:
Custom event rendering
You can use fullcalendar's eventRender option to customize how events are rendered in the calendar. However, only certain event attributes are watched for changes (they are id, title, url, start, end, allDay, and className).
If you need to automatically re-render other event data, you can use calendar-watch-event. calendar-watch-event expression must return a function that is passed event as argument and returns a string or a number, for example:
$scope.extraEventSignature = function(event) {
returns "" + event.price;
}
<ui-calendar calendar-watch-event="extraEventSignature(event)" ... >
// will now watch for price
In the docs, it is advised to use viewRender callback:
There is no mechanism to $watch the displayed date range on the
calendar due to the JQuery nature of fullCalendar. If you want to
track the dates displayed on the calendar so you can fetch events
outside the scope of fullCalendar (Say from a caching store in a
service, instead of letting fullCalendar pull them via AJAX), you can
add the viewRender callback to the calendar config.
$scope.calendarConfig = {
calendar:{
height: "100%",
...
viewRender: function(view, element) {
console.log("View Changed: ", view.start, view.end);
}
}
};

Kendo multiselect populate previously selected items using odata with paging. (AngularJS)

I'm using the kendo MultiSelect with odata paging and using the angularJS integration. Populating the data from scratch works great. When I want to re-populate the data from initial data then I seem to have a problem.
Cause of the problem:
The data only gets populate from the initial or previous dataset. So, if I the paging size is 10 then only products that exist in the first page will be displayed as normal. All product that don't fall within the first page will just not be displayed.
Possible workarounds:
Increase the page size. I have used this on other pages where the results are quite small. However this is not a realistic work around as we are expecting much bigger datasets in the future ( hence using odata in the first place)
Was thinking we could possibly do some sort of initial sorting. However this could also be slow and could still be a problem if there were more items selected than exist in the first page.
Ideal solution
Is there a way to tell kendo component to load all data based on current value? This will then build the required odata call and populate the component.
Example of the current issue:
http://dojo.telerik.com/ODaLe/2
I worked 2-4 hours to find a solution for this. Dunno if yall would like it, but it might help somebody, so I'd type it here. Following are the steps:
Step 1: Create the data source
First, setup the dataSource object which you would be using for reading remote data (for offline data, improvise by reading the API).
var dataSource = new kendo.data.DataSource({
dataType: "jsonp",
transport: {
read: {
url: options.source,
type: 'POST'
},
},
serverFiltering: true
});
Step 2: Load the selected items
This can be tricky as you need to have the selected item IDs on the client side. For me, I did it by adding a data-options-selected="1;3;9" attribute to my select element. Later, in my JavaScript, I split this attribute by ";" and retrieve an array of selected IDs. Lets say these values are in var valuesArray;
Once we have an array of selected IDs, we need to read them from the data-source. In my case, it was remote, so I ran a dataSource.read() with filters as under:
dataSource.read({
filter: {
logic: 'and',
filters: [
{
field: options.dataValueField,
operator: 'equals',
value: options.value
}
]
}
});
On the server side, this should return an array containing the items having the given identifiers. Thus, we now have those items on the client-side as well.
Step 3: Set values for the widget
Now that the value related data is loaded, we can set the values for the widget using the values() method. Here, $el is the jQuery object representing the select element which I was using for multiSelect.
var oWidget = $el.data('kendoMultiSelect');
oWidget.value(valuesArray);
That's it! One multiselect widget pre-loaded with values, ready to rock and roll. Served my purpose. Dunno if any short-cuts exist.
When using Kendo with Angular, you want to use the k-rebind attribute to refresh the pulldown options + update the picker with the values in your $scope.countries object when it changes.
If you want like the picker to update when $scope.products changes as well, you can initialize the picker using a k-options attr pointed to an object in your controller, and set the k-rebind to that object.
This kendo tutorial provides a useful example, also using odata paging.
http://docs.telerik.com/kendo-ui/web/multiselect/how-to/AngularJS/pre-select-items

Resources