Integrating external files with AngularJs - javascript

I've just started using AngularJs.
I need to use the SunCalc module to calculate sun positions for my app.
I have no idea on how to integrate the file to the app and how to access his different functions while respecting the AngularJs structure. Where to put the file? How to call a function? etc...
Here is a link so you can quickly see the structure of the SunCalc module and hopefully help me.
https://github.com/mourner/suncalc/blob/master/suncalc.js
Thanks a lot for your help!

Since this library exposes global SunCalc object with bunch of methods, what you can do is simply wrap this lib into custom service.
app.factory('SunCalc', function() {
return window.SunCalc;
});
Then you could use it like this in controller:
app.controller('MainCtrl', function($scope, SunCalc) {
$scope.position = SunCalc.getTimes(new Date(), 52.3667, 4.9000);
});
In this case you can event add your own methods to this service without messing with original library.
Note, that technically you could use globally accessible SunCalc without creating one more service for this. However using services offers sertain advantages: you can rename it easily, it allows to facade original library API, using global variables error-prone, etc.
Also remember to include script tag before Angular script tag.
Demo: http://plnkr.co/edit/rbATLGfGE2kx32tmEEoX?p=preview

Related

Using Angular Dragula without RequireJS

I would love to implement Drag and Drop in my Angular project using the angular-dragula module (https://github.com/bevacqua/angular-dragula). However, it seems to be heavily dependent on RequireJS. I've not used Require for a while and only then for an example app or two. Is there an easy way to untangle Require from this module?
The author seems to think it is simple (https://github.com/bevacqua/angular-dragula/issues/23) and has shut down similar questions as well without a real explanation. I've looked at the code and don't see how to load the module without adding RequireJS to my project (which I don't want to do). Am I stuck with either not using this module or adding Require or is there a way to use this without Require?
OK, after help from those who commented (thanks everyone!), I was able to get this to work. There are a couple things that you need to do. First, I was bundling this module with the rest of my modules and trying to call it. That will not work because it needs to initialize with a parameter (angular). Therefore, you need to do the following:
Add a reference to angular-dragula.js (or the min version) to your index.html page below the declaration for angular but above where you create your app.
When you declare the dependencies for your app, specify angularDragula(angular) (not in quotes).
Use dragula as you normally would. If you need to access the service, the name would be angularDragula.
For example, here is my declaration of app:
var app = angular.module('app', [
'ngRoute',
angularDragula(angular)
]);
And then to get a simple list to be drag and drop capable, this is my html:
<div dragula='"bag-one"' dragula-model="vm.items">
<div ng-repeat="item in vm.items">{{ item }}</div>
</div>
Note that I do not declare angularDragula anywhere, unlike the examples. In the example the author gives, he requires angular and creates the angular variable and then he requires angular-dragula and creates the angularDragula variable. This is not needed if you are not using RequireJS as long as you load the scripts in the right order.

Code seperation in AngularJS

I'm quite new to AngularJS so please bear that in mind when reading this question...
I have some functions that I would like to make globally available to different modules within my website, plan is to have pages performing their own functions in a single page app style (so a user list / create / modify would be one page, and a product list / create / modify would be another). I would like to have some shared logic, say utility functions, and also user authorisation that can be shared between the different page modules.
This leads to my question.
Assuming I have all the account functions encapsulated within a service (app.factory('account, etc etc...') for example) and separated into it's own JS file, is it better to place it within it's own module and using dependency injection like so:
var accountMod = angular.module('accountModule', ['dependencies']);
accountMod.factory('account', ['dependencies', function (...) { }]);
Or just assume the name of the app variable will always be app and express it like so:
app.factory('account', ['dependencies', function (...) { }]);
Functionally both of these work, but I am trying to use best practices. The second option seems limited, I have never been keen on assuming variable are the same name throughout, for me the dependency injection method seems better but I have seen many examples of both styles out there!
Any help is much appreciated!
Really nice question. There are subtle things in this.
I think it would helpful to use following code, which is using module.
var accountMod = angular.module('accountModule', ['dependencies']);
accountMod.factory('account', ['dependencies', function (...) { }]);
However with help of angular provider and adding module level config we can mock object or service. Eventually this will increase the test ability of code.
If there are multiple services under accounting, then I would prefer to group them inside module.
These are my aspect of to look at it. Please add more if you found.
Thanks.
Just my 2 cents on your code examples.
The following approach is not recommended:
var accountMod = angular.module('accountModule', ['dependencies']);
accountMod.factory('account', ['dependencies', function (...) { }]);
A best practice is to only have 1 component per file, therefore no need to define a variable. Take a look at this: https://github.com/johnpapa/angular-styleguide#definitions-aka-setters
If you are just starting out with Angular, I recommend that you go through the rest of John Papa's Style Guide.
I love the structure that angular fullstack generator for yeoman has.
https://github.com/DaftMonk/generator-angular-fullstack
You can see how each module and component is separated and inside, de factory, services, directives, etc. and their associate test are split in one file per functionality.
This probably is overkilling for your propose, you can take only the angular idea.

Custom directives on AngularJS pages without specific ng-app module set

I have some simple pages that don't need a specific application module to be provided in the ng-app attribute. But those pages also use some of my custom directives.
As it seems natural I've put all my directives in separate namespace (namely module) i.e. MyApp.Directives.
This is all great when I also provide my application module, because I add MyApp.Directives as dependency and it works.
angular.module("MyApp", ["MyApp.Directives", ...])
But. As said I also have some very simple pages, that don't really require any particular application module because they don't need any custom controllers or anything. They're just driven by ng-... attributes/directives.
Question
I know I can simply add all my custom directives to ng module and they will become accessible to all pages. Those with custom application module and those without. But this beats the purpose of modules, so I'm wondering if there's any other way to tell dependency injector of my additional directives/filters?
I would like to avoid any unneeded code in my application to keep is small and maintainable. (what AngularJS is all about). What I'm looking is actually some sort of hack that I'd be using in my directives' files to make ng module aware of my directives but without adding them to ng module directly... A rather advanced Angular question as it likely involves some internals manipulation.
I've tried manully adding my directives' module to angular.module("ng").requires array but that didn't do the trick.
#1) If you only have one module you can do it with ngApp:
<html ng-app="MyApp.Directives">
#2) If you have multiple modules you can use angular.bootstrap like so:
angular.element(document).ready(function(){
angular.bootstrap(document,['MyApp.Directives','MyApp.Filters']);
});
#3) Or just create a simple module for declaring dependencies:
<html ng-app="myApp">
......
<script>
angular.module('myApp',['MyApp.Directives','MyApp.Filters']);
</script>
If we could only write something like this:
<html ng-app="MyApp.Directives MyApp.Filters">
I made a patch to the source code:
function angularInit(element, bootstrap) {
// some code
if (appElement) {
bootstrap(appElement, module ? module.split(/\s+/) : []); // split by spaces :)
}
}
Here is a demo: http://plnkr.co/edit/kSrY3WYzLG39NJ4UgTRM?p=preview

How to configure factory externally in AngularJS

Say I am building a C# application with AngularJS.
I want to set up configuration object that comes from server side and basically inject that configuration into a factory. Where the factory resides in another .JS file.
How would go about doing that?
I have a JS fiddle example set up here:
http://jsfiddle.net/f89tS/7/
You could use module's constants for configuration objects coming from the server. Using constants is pretty easy, you could generate this on the server-side:
app.constant('CONSTANTS', {zoomLevel: 8});
and then, in your factory you can inject constants:
app.factory('map', function(CONSTANTS){
return {
zoomLevel: CONSTANTS.zoomLevel
};
});
Constants are really good for the server-generated settings since, once generated and sent to the client those can't change.
Finally, here is the working jsFiddle: http://jsfiddle.net/pkozlowski_opensource/JZcys/1/
Here is an example of how I accomplished something similar by wrapping my bootstrap call around my own run method.
It then uses a naming convention to inject configuration options inline from your aspx page, which could be set via c# property.
I don't know if this is the 'angular' way, but it has worked well thus far.
http://jsfiddle.net/xpressivecode/dVM9b/

Unique instances of Javascript self-executing anonymous functions

I have created the PHP side of a modular AJAX/PHP framework and now I am trying to implement the client side.
From my previous experience with modular web applications I know that sometimes multiple instances of one particular module are needed. For example, a web based two player game with page parts for each user.
On PHP side I have assigned a unque ID to each constructed instance of the module and I can pass this UID to the browser but I have no idea how to implement the Javascript side of this module instance.
Modules can be loaded all in one go or loaded separately through AJAX (I am using jQuery).
Now I am using a modular approach that I found in some article, but I can redesign it in some other way if that would help to solve this issue without sacrifising modularity and private/public code separation. For now let's say I have a js file with the following:
//Self-Executing Anonymous Func
(function( MyModule, $, undefined ) {
// My Uid
MyModule.UID = "";
//Public Method
MyModule.onLoad = function() {
alert("Hey, you loaded an instance of MyModule with UID " + MyModule.UID);
};
//Private Methods follow
function somethingPrivate( ) {
}
}( window.MyModule = window.MyModule|| {}, jQuery ));
I am using Smarty for templates. Let's say, I have a simple module template like this:
<div id="{$contents.moduleuid}">
here goes the contents of the module which can be accessed from MyModule Javascript code by using this unique moduleuid
</div>
I have set up the server side so each module automatically appends additional template with Javascript:
<script type="text/javascript">
/*
TODO: here I have access to the {$contents.moduleuid}
But I have no idea what to put here to create a unique instance of MyModule
(also it might need loading js file if it was not loaded yet) and I should also set for
this instance MyModule.UID to {$contents.moduleuid}
and also call MyModule.onLoad for this instance after it has loaded its Javascript.
*/
</script>
I am not experienced with advanced Javascript topics so it is unclear to me how I can create a separate instance of MyModule for each module which gets construced server-side? Is it possible at all to create instances of self-executing anonymous functions? If not, then how can I implement and clone Javascript objects with separated private/public code?
My recommendation is to keep the client side and server side loosely coupled. Try to build your modular client application completely with HTML/JS without PHP tricks on it. As I understand, each of your module (or UI component) need to be loosely coupled from the others. In such case there are several other concerns you might need to look for:
How to keep your UI component structure (html), presentation (css) and behavior (JS) self contained (for example in a single folder), so that it can live or die independently
How these self contained components interact with each other
How to manage the configurations/settings of your UI components
Should you be using MVVM or MVC pattern to organize and bind the view to your PHP model
Who decides when to create/show/hide your UI components (for example based on URL for bookmarking)
If your client is a large and complex application, you might need to look for other concerns such as JS optimization, unit testing, documentation, product sub modules, etc.
Have a look at the BoilerplateJS Javascript reference architecture we put forward at http://boilerplatejs.org. It suggests ways to address all concerns I discussed above.
Since you are already using jQuery, you could create a jQuery plugin. The plugin should behave the way you need, and I believe you won't even need a unique ID. Considering each of your module's instance is contained in a div with class module-container, your jQuery code for adding client-side behavior to the divs would be something like this:
$(function(){
// DOM content is loaded
$('.module-container').MyPluginName();
});
The minimal plugin code would be (considering it's in a separate .js file):
(function($){
$.fn.MyPluginName = function() {
// Return this.each to maintain chainability
return this.each(function() {
// Keep a reference to your unique div instance.
var $this = $(this);
// Plugin logic here
});
};
})(jQuery);
If you are using jQueryUI, I also recommend you also look into the "widget factory" (intro, docs), which serves as a base for building powerful, normalized jQuery plugins.

Categories

Resources