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.
Related
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.
Currently looking at upgrade paths from Angular 1 -> Angular 2 and one things we've done with our Angular 1 work is reuse some of our components on public facing non-app pages.
These pages are effectively static HTML (though they are rendered by Rails) and then some Angular 2 components are dropped into the page in places. This worked from with Angular 1, we simply bootstrapped the document element with a module that provided the directives and components we needed. There is no routing at all.
With Angular 2 it looks like it is all or nothing. You declare a single root component and everything is rendered through that. This would be a big shift for us and I'd like to avoid changing how we are doing things on these public facing pages.
Is it possible at all to just use Angular 2 components as needed in static HTML pages or will we need to move to a single root element SPA design?
In a nutshell, what I'm asking is if it is possible to have a mix of static content with dynamic angular components sprinkled within, or must all angular components live within a single root element on the page?
So this is simpler than I originally thought. In the Angular 2 docs it has some specific wording around bootstrapping multiple apps.
Bootstrapping Multiple Applications
When working within a browser window, there are many singleton
resources: cookies, title, location, and others. Angular services that
represent these resources must likewise be shared across all Angular
applications that occupy the same browser window. For this reason,
Angular creates exactly one global platform object which stores all
shared services, and each angular application injector has the
platform injector as its parent.
Each application has its own private injector as well. When there are
multiple applications on a page, Angular treats each application
injector's services as private to that application.
So it seems clear that this is intended to be possible and that multiple apps share service resources which is what I would hope for.
I've done some trivial tests with multiple bootstrapped components and it works fine. One thing I have not yet tried is bootstrapping an Angular 2 attribute directive for use outside of Angular 2 components. I suspect that won't work and that bootstrap only works with Components and not Directives.
In terms of guidance, I would suggest that Angular 2 is not really designed for sprinkling behaviour throughout a static page and probably should not be used that way. Rather, while you may have multiple sections of your paged defined by multiple apps, that components should make up nearly all of the document/interface.
we simply bootstrapped the document element with a module that provided the directives and components we needed. There is no routing at all
That's exactly how I'm currently using Angular2. See the example at https://github.com/niczero/ng2-es5-file-upload/blob/master/demo/index.html -- some of my 'static' pages are generated by perl in the same way you are using ruby.
As an aside, being able to use your modules both ways is much easier if you embrace Universal Module Definitions
I would like to have more theoretical understanding how angular modules work.
When I would create one module 'clientApp' and I 'register' controller, services, factories, scope etc..., inject other services, factories, scope into the controllers. What objects are known to the 'clientApp' module?
Angular Modules
An efficient, production-ready controllers by encapsulating our functionality in a single core unit called a module.
In Angular, a module is the main way to define an AngularJS app. The module of an app is where
we’ll contain all of our application code. An app can contain several modules, each one containing
code that pertains to specific functionality.
Using modules gives us a lot of advantages, such as:
• Keeping our global namespace clean
• Making tests easier to write and keeping them clean so as to more easily target isolated
functionality
• Making it easy to share code between applications
• Allowing our app to load different parts of the code in any order
The Angular module API allows us to declare a module using the angular.module() API method.
When declaring a module, we need to pass two parameters to the method. The first is the name of
the module we are creating. The second is the list of dependencies, otherwise known as injectables.
angular.module('myApp', []);
When writing large applications, we’ll create several different modules to contain our logic. Creating a module for each piece of functionality gives us the advantage of isolation in which to write and test large features.
Properties
Angular modules have properties that we can use to inspect the module.
name (string)
The name property on the modules gives us the name of the module as a string.
requires (array of strings)
The requires property contains a list of modules (as strings) that the injector loads before the
module itself is loaded.
Better Read
ng-book -
The Complete Book on AngularJS
Ari Lerner
Download ng-book
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.
I have been reading a lot of docs, and I'm getting more and more confused.
I basically can't figure out the difference between a
service
directive
module
I see a lot of custom components. Sometimes they're using directives, sometimes services. It always starts with a module. Can someone explain with an example what the difference is between these three types?
From my own personal notes (mostly snippets from the docs, google group posts, and SO posts):
Modules
provide a way to namespace/group services, directives, filters, configuration information and initialization code
help avoid global variables
are used to configure the $injector, allowing the things defined by the module (or the whole module itself) to be injected elsewhere (Dependency Injection stuff)
Angular modules are not related to CommonJS or Require.js. As opposed to AMD or Require.js modules, Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfill their goals (so the docs claim).
Services
are singletons, so there is only one instance of each service you define. As singletons, they are not affected by scopes, and hence can be accessed by (shared with) multiple views/controllers/directives/other services
You can (and probably should) create custom services when
two or more things need access to the same data (don't use root scope) or you just want to neatly encapsulate your data
you want to encapsulate interactions with, say, a web server (extend $resource or $http in your service)
Built-in services start with '$'.
To use a service, dependency injection is required on the dependent (e.g., on the controller, or another service, or a directive).
Directives (some of the items below say essentially the same thing, but I've found that sometimes a slightly different wording helps a lot)
are responsible for updating the DOM when the state of the model changes
extend HTML vocabulary = teach HTML new tricks. Angular comes with a built in set of directives (e.g., ng-* stuff) which are useful for building web applications but you can add your own such that HTML can be turned into a declarative Domain Specific Language (DSL). E.g., the <tabs> and <pane> elements on the Angular home page demo "Creating Components".
Non-obvious built-in directives (because they don't start with "ng"): a, form, input, script, select, textarea. Under Angular, these all do more than normal!
Directives allow you to "componentize HTML". Directives are often better than ng-include. E.g., when you start writing lots of HTML with mainly data-binding, refactor that HTML into (reusable) directives.
The Angular compiler allows you to attach behavior to any HTML element or attribute and even create new HTML elements or attributes with custom behavior. Angular calls these behavior extensions directives.
When you boil it all down, a directive is just a function which executes when the Angular compiler encounters it in the DOM.
A directive is a behavior or DOM transformation which is triggered by a presence of an attribute, an element name, a class name, or a name in a comment. Directive is a behavior which should be triggered when specific HTML constructs are encountered in the (HTML) compilation process. The directives can be placed in element names, attributes, class names, as well as comments.
Most directives are restricted to attribute only. E.g., DoubleClick only uses custom attribute directives.
see also What is an angularjs directive?
Define and group Angular things (dependency injection stuff) in modules.
Share data and wrap web server interaction in services.
Extend HTML and do DOM manipulation in directives.
And make Controllers as "thin" as possible.
Think of a module as being a place to wire up a number of other things, such as directives, services, constants etc. Modules can be injected into other modules giving you a high level of reuse.
When writing an angular app, you would have a top-level module which is your application code (without templates).
Services are mainly a way to communicate between controllers, but you can inject one service into another. Services are often used as a way to get to your data stores and people will wrap the angular APIs, such as ngResource. This technique is useful since it makes testing (particularly mocking) quite easy. You can have services for doing other things like authentication, logging etc.
Directives are used for creating widgets or wrapping existing things like jquery plugins. Wrapping existing plugins can be a challenge and the reason you would do this is to establish a two-way data binding between the plugins and angular. If you don't need two-way data binding then you don't need to wrap them.
A directive is also a place for doing DOM manipulation, catching DOM-events etc. You should not be doing DOM-related stuff in controllers or services. Creating directives can get pretty complex. IMHO, I recommend first looking at API for something that can do what you are looking for OR ask Angular's Google Group for advice.