I'm working on two very similar projects (almost the same).
But the front end of the code is totally weak. I'm refactoring it and was thinking to use the most of the same code ( and specialize if there is a single rule for it ) for both applications and when generating the build on Grunt it generates the desired application...
I wonder if there is a more correct way to do this...
I would like to reuse as much JS and HTML as possible...
Angular JS is a framework, that perfectly divided the code into modules and make each module separate and reusable. Divide your code in modules. Each module having set of Controller, Service, Factory (REST API model), Directive (If any DOM Manipulation), Partials and CSS. Now you can use each Module separately. As in your case you have to use two different backends, make a rootScope property to determine which backend to use. According to the backend to be used configure your Base backend URL, Factories and Service and rest of directives, controllers, HTML and CSS remains the same.
Related
I am new to Angular and making a small project.
For now, I have one large App.js where I define my route config and controllers and such.
In my index.html file, I link to this script file and everything works fine, I have multiple views and a small working app.
Now I would like to extract the controllers from my big javascript file, but then, what is the best way to include all those files? I do not want to have one script tag per file.
If you are worried about the fact that you will add the files manually over and over again, you could try to automate this process using Gulp or Grunt but it will take a bit of research. What I recommend, though, is using an already set-up generator with these systems in place for you. Such a generator would be the Hottowel generator made by John Papa, which also respect his Angular Styleguide.
Whatever you choose in the end is your preference, but I recommend looking into such generators and explore their way of doing the architecture of an Angular application and then see what suits your needs best.
I'm currently using Sails for backend, which comes with an ejs view engine and a templating system which is rather neat. However, setting up Angular on the front end of things will get in the way of these functions.
For instance, I can no longer use templates, because if I have say <html ng-app="myApp"> inside layout.ejs Angular will never initialize.
Same thing should I include any ejs templates.
So what I have done now is created a index.html file inside my assets folder, turned off the Sails routes and layouts, and am purely working with Angular. This will do fine for my current project (except I can't make things as tidy as I'm used to, the boilerplate html need to sit there, etc.) but will it be a problem in other projects, I wonder?
In other words, what am I missing out on by not using ejs? How will I ever be able to get things from my Sails controllers into my views? Or won't I need to?
First this question is WIDE open to interpretation based on all sorts of variables.
If your using your APP simply as JSON delivering API, then in reality you don't need to use the template engine. So the basic premise of your question is valid.
However, their are still plenty of reaons to use the template engine.
For instance, you can still use EJS to setup your default layout and index page for your angular site.
For instance, I can no longer use templates, because if I have say inside layout.ejs Angular will never initialize.
This statement is completely wrong. I use server render templatse for my index page on a SPA in order to use my app version to point to updated assets and template files. That way old template files will not be cached when I update my app. Depending on the app the index page may be the only one to use the template engine as everything else will use static templates. Others I have the server render my templates using the template engine as well (for example: if I want to restrict certain aspects of my templates based on a user role.)
There are other reasons as well. You might try the Google Groups for sails as this is more of an open ended question.
https://groups.google.com/forum/#!forum/sailsjs
If you use Angular for frontend and SailsJs for the backend the best practice is to have two distinct applications which means you don't have use sails to render the views (No EJS mandatory ).
AFAIK SailsJS just need to be used as a REST API while Angular needs to render your views ( you could use http.post get put and delete to comunicate with your api).
Best Regards.
As sails.js is purely backend and Angular.js is purely frontend, they can work together nicely.
All you need to do is place your angular files and logic in
myapp/assets
folder. Assets folder is by default acessible on sails server url.
You can access it as http://localhost:1337/assets/file_name.
As for the ejs, if you are using any javascript framework like angular.js then it is not a requirement as all JSON api will be made in sails framework and angular will get data in JSON format.
I am using angularjs. want to load parts of a page that I package as "components", wherein a component contains its controller, template, directives and a few other assets like CSS etc. When needed, I want to load all of this on demand.
I was able to load the controller and the template on-demand by specifying a resolver for the controller and the templateUrl for the template. But is there any way I can combine them into a single HTTP request? Any examples?
Sorry forgot to add: I want to do it only on-demand, not precompiled/pre-aggregated (lets just say thats is a requirement thats been given to me). Is there a way?
You can use angular templatecache to add your html to a module and package template cache along with controller, services, directives etc.
In order to pull your Angular code and your html templates together in one request from the server, you'd need to have the templates combined in with your js. That would imply using some kind of job to process your html into js and concatenate it in with the rest of your code. Something like grunt-angular-templates might do the trick.
Edit
With the added requirement that this should be an on-demand sort of thing, I could only add (with the current information) that this sort of thing can be accomplished with bundling and request processing on the server, but the specifics on how to do this are totally dependent on your specific server stack. Often a server will have features that allow for on-demand resource bundling, or rendering of partial-views that might be helpful in this capacity.
I need advise on designing an AngularJS application with multiple complex modules and based upon the user role the module gets loaded after authentication & authorization. Some users could have access to one simple module and some could have dashboard and some could have access to 2+ modules.
There are lot of directives we have identified which can be reused across different modules. During the design phase we have identified the following things that should exist and we have answers for some of the below items, but we still need advice from experts:
A Module could have
Partials
Controllers
Directive
Services
Exception handling (HTTP Status code or Business errors)
Logging (With line number, from which function)
May also need to save the logged info in the server
Should have the ability to turn on and off logging
custom widgets via factory class (Reused in other modules)
Shared Directives (isolated scope)
Shared Modules
Shared Utilities (sorting, filtering, etc.)
Enumerators as per master data
Constants via singleton
Authentication (CSRF)
offline storage
REST services
Event handling for dispatching from one module and handling it in other
UI of the application looks like, a fixed menu bar on the top of the page with a drop down navigation on top left with multiple links depending on the user's role. When the user clicks on a link the corresponding module should get loaded in the page. There has to be an empty project which is manually bootstrapped and loads the other modules at run-time.
Our approach is to have the following folder structure:
app
assets
css
lib js
images
common components
directives
utilities
authentication
Service proxy to hold the $resource calls
Enums
Constants
Model
entity json (example customer, product, etc.)
business Module A
Partials
Directives
Services
Controllers
business Module B
business Module C
index.html
Requirejs config file
So my questions are:
How can a service inside a module talk to other module?
Module should be developed and run independently?
How the communication between module can be handled with transferring data?
How to integrate all the above elements, particularly exception handling, logging?
Developers should understand the convention we have defined?
What method to call for logging, sending info between module?
I recommend to include yeoman into your workflow and use a generator for your project, that makes a lot easier the way that you structure your app, specially if you are working in a team.
earlier this year people from angular released a document with best practices for your app structure, I'd recomment you to read it, being said that there's a generator based on those best practices named cg-angular which I totally recommend.
I'll quote from cg-angular site:
All subgenerators prompt the user to specify where to save the new
files. Thus you can create any directory structure you desire,
including nesting. The generator will create a handful of files in the
root of your project including index.html, app.js, and app.less. You
determine how the rest of the project will be structured.
regarding to your questions:
How can a service inside a module talk to other module?
you can create a folder for directives/ and services/ you are going
to reuse in different modules.
Module should be developed and run independently?
you can have several modules inside an app (you could load them as
needed, maybe using require js but this is offtopic)
How the communication between module can be handled with transferring data?
Use services to pass information between controllers, in different
modules
How to integrate all the above elements , particularly exception handling, logging?
you can do a generic error handler and a generic http interceptor for
all the modules
Developers should understand the convention we have defined?
use a generator they are opinioated and they give the order and the
conventions you need for a team.
Lots of good questions to be asking; they appear to be in two major groups -- the first is a question of code structure and the second is about metrics (logs, etc.).
How can a service inside a module talk to other module?
You should ideally be using directives for your modules. This way you can leverage the ability to link controllers via the require property. Here is a page on sharing data between directives and controllers.
Module should be developed and run independently?
I assume you're thinking about unit testing. Yes, your modules should ideally be as tightly-scoped as possible in order to make testing easier.
How the communication between module can be handled with transferring data?
This is where services are typically used. Note: services, factories and providers all mean the same thing in AngularJS, they're just declared in slightly different ways. Pick whichever one you're most comfortable with.
How to integrate all the above elements , particularly exception handling, logging?
Logging is a separate issue. The beauty of AngularJS is that you can very easily augment existing parts of the framework in order to add functionality or behaviors as you see fit. You do this using decorators. Here is an example of exception logging that I think will cover any use cases you might be interested in
Developers should understand the convention we have defined?
The answer to this is always the same: communication is how they know. Developers need to socialize the convention otherwise you'll never get buy-in.
What method to call for logging , sending info between module?
Answered above.
Code Organization in Large AngularJS and JavaScript Applications
Many developers struggle with how to organize an application's code
base once it grows in size. I've seen this recently in AngularJS and
JavaScript applications but historically it's been a problem across
all technologies including many Java and Flex apps I've worked on in
the past.
The general trend is an obsession with organizing things by type. It
bears a striking resemblance to the way people organize their
clothing.
Piles on the Floor
Let's take a look at angular-seed, the official starting point for
AngularJS apps. The "app" directory contains the following structure:
css/ img/ js/ app.js controllers.js directives.js filters.js
services.js lib/ partials/ The JavaScript directory has one file for
every type of object we write. This is much like organizing your
clothes into different piles on the floor. You have a pile of socks,
underwear, shirts, pants, etc. You know your black wool socks are in
that pile in the corner but it's going to take a while to dig them
out.
This is a mess. People shouldn't live like this and developers
shouldn't code like this. Once you get beyond a half-dozen or so
controllers or services these files become unwieldy: objects you're
looking for are hard to find, file changesets in source control become
opaque, etc.
The Sock Drawer
The next logical pass at organizing JavaScript involves creating a
directory for some of the archetypes and splitting objects into their
own files. To continue the clothing metaphor, we've now invested in a
nice mohaghony dresser and plan to put socks in one drawer, underwear
in another, and neatly fold our pants and shirts in still others.
Let's imagine we're building a simple e-commerce site with a login
flow, product catalog and shopping cart UI's. We've also defined new
archetypes for Models (business logic and state) and Services (proxies
to HTTP/JSON endpoints) rather than lumping them into Angular's single
"service" archetype. Our JavaScript directory can now look like this:
controllers/ LoginController.js RegistrationController.js
ProductDetailController.js SearchResultsController.js directives.js
filters.js models/ CartModel.js ProductModel.js SearchResultsModel.js
UserModel.js services/ CartService.js UserService.js ProductService.js
Nice! Objects can now be located easily by browsing the file tree or
using IDE shortcuts, changesets in source control now clearly indicate
what was modified, etc. This is a major improvement but still suffers
from some limitations.
Imagine you're at the office and realize you need a few outfits
dry-cleaned for a business trip tomorrow morning. You call home and
ask your significant other to take your black charcoal and blue
pinstripe suits to the cleaners. And don't forget the grey shirt with
the black paisley tie and the white shirt with the solid yellow tie.
Imagine that your significant other is completely unfamiliar with the
your dresser and wardrobe. As they sift through your tie drawer they
see three yellow ties. Which one to pick?
Wouldn't it be nice if your clothing was organized by outfit? While
there are practical constraints like cost and space that make this
difficult with clothing in the real world, something similar can be
done with code at zero cost.
Modularity
Hopefully the trite metaphors haven't been too tedious but here's the
recap:
Your significant other is the new developer on the team who's been
asked to fix a bug on one of the many screens in your app. The
developer sifts through the directory structure and sees all the
controllers, models and services neatly organized. Unfortunately it
tells him/her nothing about which objects are related or have
dependencies on one another. If at some point the developer wants to
reuse some of the code, they need to collect files from a bunch of
different folders and will invariably forget code from another folder
somewhere else. Believe it or not, you rarely have a need to reuse all
of the controllers from the e-commerce app in the new reporting app
you're building. You may however have a need to reuse some of the
authentication logic. Wouldn't it be nice if that was all in one
place? Let's reorganize the app based on functional areas:
cart/ CartModel.js CartService.js common/ directives.js filters.js
product/ search/ SearchResultsController.js SearchResultsModel.js
ProductDetailController.js ProductModel.js ProductService.js user/
LoginController.js RegistrationController.js UserModel.js
UserService.js Any random developer can now open the top-level folder
and immediately gain insight into what the application does. Objects
in the same folder have a relationship and some will have dependencies
on others. Understanding how the login and registration process work
is as easy as browsing the files in that folder. Primitive reuse via
copy/paste can at least be accomplished by copying the folder into
another project.
With AngularJS we can take this a step further and create a module of
this related code:
1 2 3 4 5 6 7 8 9 10 11 12 13 var userModule =
angular.module('userModule',[]); userModule.factory('userService',
['$http', function($http) { return new UserService($http); }]);
userModule.factory('userModel', ['userService', function(userService)
{ return new UserModel(userService); }]);
userModule.controller('loginController', ['$scope', 'userModel',
LoginController]); userModule.controller('registrationController',
['$scope', 'userModel', RegistrationController]); view
rawUserModule.js hosted with ❤ by GitHub If we then place
UserModule.js into the user folder it becomes a "manifest" of the
objects used in that module. This would also be a reasonable place to
add some loader directives for RequireJS or Browserify.
Tips for Common Code
Every application has common code that is used by many modules. We
just need a place for it which can be a folder named "common" or
"shared" or whatever you like. In really big applications there tends
to be a lot of overlap of functionality and cross-cutting concerns.
This can be made manageable through a few techniques:
If your module's objects require direct access to several "common"
objects, write one or more Facades for them. This can help reduce the
number of collaborators for each object since having too many
collaborators is typically a code smell. If your "common" module
becomes large subdivide it into submodules that address a particular
functional area or concern. Ensure your application modules use only
the "common" modules they need. This is a variant of the "Interface
segregation principle" from SOLID. Add utility methods onto $rootScope
so they can be used by child scopes. This can help prevent having to
wire the same dependency (such as "PermissionsModel") into every
controller in the application. Note that this should be done sparingly
to avoid cluttering up the global scope and making dependencies
non-obvious. Use events to decouple two components that don't require
an explicit reference to one another. AngularJS makes this possible
via the $emit, $broadcast and $on methods on the Scope object. A
controller can fire an event to perform some action and then receive a
notification that the action completed. Quick Note on Assets and Tests
I think there's more room for flexibility with respect to organizing
HTML, CSS and images. Placing them in an "assets" subfolder of the
module probably strikes the best balance between encapsulating the
module's asset dependencies and not cluttering things up too much.
However I think a separate top-level folder for this content which
contains a folder structure that mirrors the app's package structure
is reasonable too. I think it works well for tests as well.
Please have a look at the below link,
https://blog.safaribooksonline.com/2014/03/27/13-step-guide-angularjs-modularization/
I'm creating a single page web application.
I created a basic design for the app structure. This answer about this video was very helpful.
The application contains one html page. The JS code will change it's content.
The Usher will supply a module according to the URL (domain.com/#list#item1 will return an item module).
The module will use the sandbox to retrieve data from the server (that will use the Application Core for that).
The module will set the page style by passing the sandbox an key-value list and will set the page HTML in this way too.
What do you think about it. Does it decoupled enough?
Short answer: Kind of. It depends on how complex your modules are.
Long answer:
I'm working on one application that respects the Core -> Sandbox Instances -> Modules pattern like you described.
The only unanswered question about my application is this:
"What happens when Module A and Module B have a small UI component that is the same, or almost the same?".
In your case, this might be an accordion on 3 modules out of 5. This accordion might be application specific, so simply adding a jquery plugin in core, and exposing it to the modules via Sandbox will just not cut it.
I ended up with two possible solutions:
1) Use the common functionality as a special type of module that can be requested via the sandbox by other modules. This is the case when just one instance of the UI will be visible at a given time - which might be your case -
2) Use a simple prototype instantiation for my reused object and add it as a dependency for all modules that use it.