AngularJS directive in one module and template in another - angularjs

Looking for a suggestion of a good way to create an abstract directive in one module and load its template on different modules.
The scenario is the following: I have a web site split into two (web portal and backoffice) which are two different deploys. Both share a lot of modules and the layout but have different functionalities.
I would like for the menu directive and structure to be on a core/common module, but its template should be loaded by the modules, so that the core module doesn't need to know what specific deploy is being used!
I thought about using $templateCache on each module configuration process, but does anyone know a better option for this?

Yes, the only option to keep templates and the rest of the application in different JS bundles is $templateCache. Other options (directive inheritance or requireing and bundling template HTML files with Webpack) will likely result in monolithic bundles.
There's no separate template unit in AngularJS, so in order to be included in module, templates should be defined with $templateCache.put.

Related

Sails.js and Angular.js project structure and configuration for non-SPA case

I am starting a side-project based in Sails to try it. Most of the pages are server-side rendered via EJS and don't require javascript on the front-end (my landing page doesn't, my "about" page certainly doesn't etc). However, I have a few pages that have quite a lot client-side functionality and I want to use Angular, because I am mostly familiar with that framework. The routing to these pages is again handled in the server and there's really no meaning in bundling them as a SPA.
So I am trying to wrap my mind around these concerns:
Where to place the Angular app's scripts?
Is /assets/js/dependencies still the proper place? Wouldn't placing them there make the Grunt task inject them in layout.ejs and thus in every page?
How to conditionally load the Angular base and it's components (controllers, services, etc)?
Sails uses views/layout.ejs as a base layout for loading project-wide styles, templates and scripts. Each page's controller handles injecting the body part into this layout according to the view "partial" that has been developed for that page. Is this view "partial" .ejs file the appropriate place to conditionally load the Angular app files in only the pages that require them?
How to add min/conctact/uglify of Angular' script sources in Grunt tasking?
All the Angular related files will need to be concatenated, minified/uglified for production. This will need to be a new js concatenated file to be loaded in appropriate pages apart from the "generic" js file that currently Sails tasks create and is loaded in every page. So we're essentially talking about two concatenated js files for the client side. One that is globally loaded, and the Angular one that only the pages that need it load. Which parts of the build/tasking procedure will require modifications? Some examples or resources to check would be highly useful here.
Where to place the Angular app's scripts?
Is /assets/js/dependencies still the proper place?
No, just put your angular.min.js in your dependencies folder, but not your Angular app's script. You need to put all you Angular app in the assets/js folder ( or in a sub-folder, but not in dependencies )
To be sure that each file of your app will be loaded in the right order (for example you need to load first the Js file which inject your angular app's dependencies), you can modify the tasks/pipeline.js file, and specify the order you want : You need to modify the jsFilesToInject array which contains all the Js files to load in the right order.
For example for your project :
var jsFilesToInject = [
// Load sails.io before everything else
'js/dependencies/sails.io.js',
// loading angularJS
'js/dependencies/angular.min.js',
// all the rest in dependencies
'js/dependencies/**/*.js',
// loading first AngularModule definition
'js/app/app.module.js',
// all the rest of the angular application
'js/app/**/*.js'
];
For your other question I think you need to look at the tasks/config/sails-linker.js file, that inject all the Js scripts in the <!--SCRIPTS--> tags in your HTML code.
I hope that it will help you and that I'm not too late !

Angular app with more than one module and general functionality

Angular modules are a kind of namespacing feature that we know from the .net world. Keep things contained in modules.
The problem is that I would like to do this:
I would like certain pages that don't have any specific client-side functionality but use custom directives to just define ng-app or ng-app="xyz" to just work; I don't want to introduce an additional Javascript code(file) just to make it work.
I would like to have pages with different modules i.e. App.Main and App.Specific; Both of these pages should use the same directives from #1 and use them.
I would like to contain general stuff inside App.General module, and then have additional modules like mentioned App.Main and App.Specific.
Question
Which module should directives be defined in and how should dependencies (if at all as they don't call each other's code in any way) between these modules be for directives and pages to work as expected?
If I am understanding your question correctly, my suggestion would be to define several angular app modules in the same javascript file and activate the appropriate one for each page by the ng-app="App.General" directive vs ng-app="App.Specific". So you could have have a single concatenated javascript file that contains:
angular.js
any third party dependencies you are using
your custom directives, services, controllers, etc
I would suggest using "very granular modules" as recommended at the NYC AngularJS Meetup Feb 2014 at 24m in this video and putting each individual directive and service into it's own module.
But it would also be fine to group all your shared directives into a single module called "App.Directives", for example.
your general code defined by angular.module('App.General', ['MyDirective']); (plus additional dependencies)
your specific code defined by angular.module('App.Specific', ['MyDirective', 'MyService']); (plus additional dependencies)
Also note that you don't have to declare your app dependencies as a literal array of strings. You could do var directives = ['Dir1', 'Dir2']; Then angular.module('App.Specific', directives.concat('MyService', 'MyController')); to express that the specific app uses the same directives as the general app.
Each page could include the same <script src="/bundle.js"></script> HTML (thus it would be loaded from the web only once then cached).
General pages would include ng-app="App.General" in their HTML. Specific pages would have ng-app="App.Specific".
certain pages that don't have any specific client-side functionality but use custom directives
So the directives technically constitute "client side functionality" since they will be rendered to their final HTML in the browser. So you will need to load angular.js, the modules containing your directives and at least one line of your own code to define an app and declare it's dependencies on the modules that provide the custom directives you are using.

Include View-Specific Scripts with AngularJS

relatively new to Angular so I'm not sure what the best practice is for this scenario. I have a fairly simple index.html that include an ng-view in the middle. Later on in the html I need to include page(view)-specific js scripts after some of the generic app-level scripts load. What is the best practice for doing so?
Pseudo-Code
[ng-view]
[generic stuff for all pages]
[view-specific scripts]
By default AngularJS needs all the script related to your ng-app module loaded at one go, which is called bootstrapping the app. What this means is that if the scripts are related to AngularJS such as controller, directives and service, routes have to be loaded together in the script block, they cannot be loaded on demand.
There are some plugin that allow lazy loading such as these
https://github.com/matys84pl/angularjs-requirejs-lazy-controllers
https://github.com/nikospara/angular-require-lazy
https://github.com/ocombe/ocLazyLoad

Does Angular.JS have a module loader or do I need to use script tags?

I am using Angular JS. I wish to put unrelated code (ie, which is not a factory, service, controler, etc) in additional, separate modules, in a similar way one would with AMD or CommonJS.
At the time of writing, a search for 'Angular.JS make new module' using Google does not return any documentation on making Angular.JS modules.
I have a found a post on the Angular.JS Google Group that seems to indicate that instead of loading dependencies dynamically like other module systems, in Angular.JS dependencies must be inserted as additional script tags.
Is there any documentation on making Angular modules (which is not limited to controllers, services, or other angular concepts)?
Is the statement about script tags true? Do I need to manually add script tags for every module I may use?
Looking further into the various Angular boilerplate apps, apps manually load every part of their apps via script tags. Unlike other systems, Angular 'modules' don't take care of actually loading dependencies, they just inject them once already loaded.

Incorporate AngularJS into existing modular application

I'm trying to find the way of incorporating AngularJS into existing application. Application is modular, so every module has HTML markup and JS script files. Modules are loaded with requirejs and jQuery (for loading markup).
I would like to use AngularJS features in some of the modules, having in mind the possibility of migrating to AngularJS in future. So ideally I want something like this:
define([ 'angular' ], function (angular) {
return function (element) {
// The "element" parameter contains the reference to
// the detached DOM node that contains the markup.
// And what I think should be done is compiling
// or initializing AngularJS with the given DOM HTML fragment
// and with controller, etc.
angular.doSomething(element, ...something...);
// The application module engine will inject the returned element
// into the DOM tree.
return element;
};
});
Any ideas? Thanks!
Just following the tutorial, specifically Step 2 (http://docs.angularjs.org/tutorial/step_02) will show you how to just do a single controller on the page with some simple functionality.
You can just use this, or you can start expanding it by modularizing it as in Step 7. By creating an module you can then add directives and services and take advantage of all that Angular offers. You don't necessarily need to configure routes or anything, but by creating an app module, you can incorporate other modules or services offered throughout the web or by Angular.
AngularJS isn't designed to really run alongside other frameworks and be used for little bits and pieces. You could hack it together to do this but it'll probably become very messy. Angular is much better suited to becoming the basis of the entire app.
Something like jQuery is great for dropping into an app and adding functionality, but angular is far more complex.
If you do want angular to take control of certain parts though, take a look into the ng-controller directive and how it works. Then in your standard markup you'd just add the ng-controller attribute to any element, and then add a new angular controller to your javascript. It would then manage that DOM element.
Look into angular controllers for more info on that. But as I say, I'd suggest making the app entirely Angular rather than trying to just add angular bits to it

Resources