Fullcalendar v5 eventContent not working with angular js - javascript

I'm using Fullcalendar v5 in angular js, and i'm trying to make a custom event with:
https://fullcalendar.io/docs/content-injection
eventContent: function(arg) {
return { html: constructEvent(arg) }
},
The thing is that if i add:
"<div ng-repeat='user in arg.event._def.extendedProps.users' class='avatar'>"
"<p>{{ user.name }}</p>"
"</div>"
it won't render. It's like it's outside angular's scope. Can someone tell me if there is a way to construct this with angular js logic? Or i need to use vanilla js to iterate through items. Also ng-click doens't work. I tried even with triggering safeApply digest but no results.
I just want to edit the event inside calendar with the framework i'm using, and use angular events inside it to open sidebars or to make api calls.

Rendering Events
with your line <div ng-repeat it seems that you'd like to iterate through an array of events to display on your screen. If this is the case, you simply need to render the events via the 'events' parameter.
https://fullcalendar.io/docs/event-object
Regarding eventContent (the contents of an event, such as title, subtitle, img, etc)
It looks like at the minute only React JSX Nodes are supported. Vanilla JS is your only way forward.
https://fullcalendar.io/docs/content-injection

Related

Add dynamic HTML from JavaScript in Angular 2/4/5 and bind events

I am trying to add new HTML code via AJAX to an Angular 5 app and add click event to the elements. But the click event doesn't work as expected, I can't use the 2 way data-binding way because I am using the jQuery data-tables plugins and he add the HTML to the Dom and not the angular template.
I have tried:
<button (click)='myClassFunction()'>Click!</button> this line does nothing
<button onclick='myClassFunction()'>Click!</button> this line said myClassFunction is undefined
<button onclick='this.myClassFunction()'>Click!</button> this line said myClassFunction is undefined
How can I bind this click event to my function?
Angular is written in Typescript.
When you serve or build your application, this typescript application is then compiled, minified and uglified to native Javascript.
This means that your
(click)="myClassFunction()"
Will become something along the lines of
onclick="srgu.gferu()"
And as you can see, Angular won't recognize that.
It doesn't matter if you use JQuery or plugins : that is the way Angular works.
To do that, you will need to create window functions, or global functions.
myClassFunction() {
// Create your window function, make it tslint compliant
window['myWindowClassFunction'] = () => {
// Your function's logic here
};
}
Now, in your appended HTML, you need to write
<button onclick='window.myWindowClassFunction()'>Click!</button>

ng-click on X3Dom shape

I'm trying to use angular.js with X3DOM. I want to be able to create a shape (in this case a sphere), and have it do something when the user clicks on it. I've been able to get it to work using the traditional onclick method. However, when I switch to angular's ng-click, to event fails to fire. Unfortunately, since the data that I want to display is stored within the controller, using the angular onclick is kind of a must.
I've done a bit of research and supposedly angular.js isn't 100% compatible with X3DOM, so I'm guessing this is part of the issue. But I've been using other angular directives without an issue. Does anyone know if there's a way around this error?
Code Sample:
<transform translation="{{datum['Market Loading']}} {{datum['Growth Loading']}} {{datum['Size Loading']}}" ng-repeat="datum in energy.data" ng-hide="energy.hide === true" onclick="">
<shape>
<appearance>
<material class="energy" diffuseColor="{{energy.color.join(' ')}}" transparency="{{energy.hide}}"></material>
</appearance>
<sphere radius="{{datum['Specific Risk']}} ng-click="DO SOMETHING"></sphere>
</shape>
</transform>
I guess you need to use the standard onclick event, as X3DOM needs to translate click events on the canvas to the actual node inside the tag and x3dom does not know abaout ng-click.
In your standard onclick handler you can retrieve the angular scope aganain an fire your angular click handler from there.
Something like this (untestet):
<sphere radius="{{datum['Specific Risk']}} onclick="myclick(event)"></sphere>
and a standard onclick event handler:
function myclick(event) {
// TODO: add more error handling
var scope = angular.element(event.target).scope();
scope.yourAngularClickHandler(event);
}
This is a bit ugly and getting the scope from the dom element on every click may also be slow. I'm doing something similar with an onmousemove event and the speed is okay. Don't forget to add some error handling for the cases where the scope is not ready or cannot be found etc.

Angularjs: is this the right place to use a directive?

I've recently switched from jQuery to Angularjs and I am in the process of re-coding some pagination logic for the links ("Next", "Previous", etc.) that were written in jQuery-style Javascript previously.
Each link has an ngIf condition (for example, the "Previous" link won't show if you're on page 1) plus an ngClick event, which essentially updates a scope variable called $scope.pagination.position that determines which results are displayed in the table.
My original code was something like this (simplified for clarity):
Template
<a ng-if="pagination.position > 0" ng-click="pagination.first()">First</a>
Controller
$scope.pagination = {
first: function() {
this.position = 0;
}
}
Then I learned more about directives, and how most DOM elements that aren't static HTML should be created using a directive. So I switched each link (since each has it's own display rules and behaviour on clicks) to its own directive, like so:
Template
<a pagination-first></a>
Directive
app.directive('paginationFirst', function() {
return {
link: function(scope,el,attr) {
scope.pagination.first = function() {
scope.pagination.position = 0;
}
},
replace: true,
template: '<a pagination-first ng-if="pagination.position > 0" ng-click="pagination.first()">First</a>'
}
});
I'll cut straight to the chase : am I doing directives wrong? All that's happened, from my perspective, is I've flipped from having logic in my template to having a template in my logic, and I've defined the click event function in the directive rather than in the controller.
Is this even an appropriate time to be using a directive?
I'd like to learn best practices, so I'd love to know if I've missed the point and if the original templated-based ngIf and controller function approach was fine, even with longer and more complex ngIf conditions than the one shown.
If I want to add specific behaviors to a dom or dom list then I normally create a directive. As per angular js perspective the dom manipulation should only be done through directive (For me it is the best place, sometime I have to disobey this due to my lack of knowledge ). I specially found directive use full while creating a widget. In one of my project there was a part where a section is dedicated to display an image and also upload the image. I just use the directive on the top div, with the help of link function I attached the event handlers to various child dom. And as my project doesnot require an isolated scope (as this widget was all used in a single project and the outer scope was under my control) . So it worked like a charm. I cerarted the directive once. And used that widget through rest of the project as it's behavior and design (of the widget ) was same through out the project. For the pagination widget you can create a directive. Take the directive attibutes value as the input of the pagination parameters. Like calling script, limit offset. Container identifier to update the content. Then you can solely concentrate on the pagianation behavior. But from my experience (as I am also not so experienced in angular js), sometimes it becomes a little hectic to develop a directive and and use that throughout the project. As in some places we need to modify the behavior of the directive. And for this it may breaks elsewhere. But I know as I learn more I will be more efficient to handle this kind of situation. Hope my experience will help you.

Meteor: what can I use instead of setTimeout to reactive DOM changes?

I use materialbox (jQuery plugin to display Material Design lightbox style) when a new photo was taken from mobile end added to a dynamic list.
When photo is ready and visible in the DOM, a template event starts:
Template.item.events({
'click .materialboxed':function(e,t){
setTimeout(function(){
$('.materialboxed').materialbox();
},0)
}
});
the DOM:
<div class="col s2" style="text-align:left;">
{{#if pictureExist}}
<img src="{{picture}}" alt="" class="responsive-img materialboxed"> <!-- notice the "circle" class -->
{{else}}
<div class="takePicture"><i class="mdi-image-photo-camera small"></i></div>
{{/if}}
</div>
Is there a best Meteor way instead setTimeout to instantiate jQuery code in reactive data?
Thanks
Try removing the timer.
Template.item.events({
'click .materialboxed':function(e,t){
$('.materialboxed').materialbox();
}
});
It should work.
I think what you have is perfectly fine in the Meteor world.
Since you do not want to instantiate anything when the Template is created, and you are not looking to track the state of the Template, then registering an event to call that bit of jQuery code seems like the straightforward way of going about it.
EDIT: Looked at your response to another answer, here is what you need:
Template.item.rendered = function () {
# this.$() will only look for elements inside this template
this.$('.materialboxed').materialbox();
};
To optimize your implementation a bit, we only initiate your jQuery plugin on the element that is clicked on. Instead of initializing it onto every element with a .materialboxed class each time an item template is rendered.
The template.$() function works exactly like jQuery but only finds elements within the template. I am not sure how this function works with jQuery plugins, but you could first return the exact element using this function, save it, and then convert it to a jQuery object manually.
More info on this here:
http://docs.meteor.com/#/basic/Blaze-TemplateInstance-findAll

Javascript - Execute HTML/Angular ng-include

I'm using AngularJS to design a small app for searching. I have a div that's currently empty, and after running a function, for it to replace it with a div that has ng-include. The div replaces just fine, but ng-include doesn't load up.
I'm currently running the following in console for testing to see get it running. How would I go about getting this to work? Any help is appreciated!
document.getElementById("resultsDiv").innerHTML = '<div ng-include="" src=" \'sr.html\' "></div>';
read about angularjs $compile function
I don't know why you need to make this JavaScript-call, but its definitely no the 'angular-way'. If you need to conditionally include html, i would recommend using ng-if, ng-hide, ng-show or even ng-switch.
You could do something like this:
// somewhere in your controller
$scope.triggerSomeInclude = true;
// in your template
<div ng-if="triggerSomeInclude">
<div ng-include ="'someFile.html'"></div>
</div>
Another approach would be using a directive. They are the only place, where selecting an element directly could make sense (although even there it usually doesn't to select an element via id). But as I said, it's hard to stay what the best method would be, as I'm not sure what you're trying to achieve.
Although you're not using jQuery, what you're trying to do looks very jQueryesque (awful word) as you're selecting an element directly seemingly totally detached from the $digest and $compile-cycles of angular, so I also would recommend to read this answer:
"Thinking in AngularJS" if I have a jQuery background?
In the end, the method I used was templating example used for ngInclude.
http://docs.angularjs.org/api/ng.directive:ngInclude
Inside my controller, for example, by default it would set the following:
$scope.mainDivTemplate = {url: 'partials/test1.html'}
If I wanted to switch it to something else, I'd call a function that would look a little something like this.
$scope.loadHome = ->
$scope.mainDivTemplate = {url: 'partials/home.html'}
$scope.$apply()

Categories