├── LICENSE ├── README.md ├── angular2readiness.md ├── best-practices.md ├── cool_stuff.md ├── router.md ├── rxjs.md ├── services.md └── testing-http-services.md /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 Community FAQ 2 | 3 | # Table of Contents 4 | 5 | ## [General Angular 2 Questions](angular2readiness.md) 6 | - [When will Angular 2 be released?](angular2readiness.md#when-will-angular-2-be-released) 7 | - [Seriously though, can I get an estimate?](angular2readiness.md#seriously-though-can-i-get-an-estimate) 8 | - [Is it ready for me?](angular2readiness.md#is-it-ready-for-me) 9 | - [Beta](angular2readiness.md#beta) 10 | - [Stability/Bugginess](angular2readiness.md#stabilitybugginess) 11 | - [Known Regressions](angular2readiness.md#known-regressions) 12 | - [API Stability](angular2readiness.md#api-stability) 13 | - [Documentation](angular2readiness.md#documentation) 14 | - [Ecosystem](angular2readiness.md#ecosystem) 15 | - [Community/Blogs/Support/Etc...](angular2readiness.md#communityblogssupportetc) 16 | - [Do I have to use Typescript?](angular2readiness.md#do-i-have-to-use-typescript) 17 | - [Do I have to use a build system? What build system should I use?](angular2readiness.md#do-i-have-to-use-a-build-system-what-build-system-should-i-use) 18 | - [Router](angular2readiness.md#router) 19 | - [Internationalization](angular2readiness.md#internationalization) 20 | - [Animation](angular2readiness.md#animation) 21 | - [Twitter Bootstrap/Material Design](angular2readiness.md#twitter-bootstrapmaterial-design) 22 | 23 | ## Setting up Angular 2 with... 24 | - SystemJS 25 | - Webpack 26 | - JSPM 27 | - Rollup 28 | - ES5/ES6 (no ts) 29 | - Others (are there any others?) 30 | 31 | ## [RxJS](rxjs.md) 32 | - [Adding operators (map is not defined)](rxjs.md#adding-operatorsobservables-map-is-not-defined) 33 | - [Full RxJS](rxjs.md#full-rxjs) 34 | - [Individual Operators](rxjs.md#individual-operators) 35 | - [Loading operators individually for RxJS + Angular2 + SystemJS](rxjs.md#loading-operators-individually-for-rxjs--angular2--systemjs) 36 | - [Configuration for full RxJS](rxjs.md#configuration-for-full-rxjs) 37 | - [Configuration for individual observables / operators](rxjs.md#configuration-for-individual-observables--operators) 38 | - [Simpler configuration](rxjs.md#simpler-configuration) 39 | - [Alternative configuration](rxjs.md#alternative-configuration) 40 | - [Reference](rxjs.md#reference) 41 | - [What are observables and where can I learn more about them and RxJS?](rxjs.md#what-are-observables-and-where-can-i-learn-more-about-them-and-rxjs) 42 | - [Redux + Rx + Angular2 / ngrx](rxjs.md#redux--rx--angular2--ngrx) 43 | - [Redux](rxjs.md#redux) 44 | - [ngrx](rxjs.md#ngrx) 45 | 46 | ## [Router](router.md) 47 | - [How do I protect routes?](router.md#protecting-routes) 48 | - [How do I resolve data before a route activates?](router.md#resolving-route-data) 49 | - [How do I handle invalid URLs?](router.md#handling-invalid-urls) 50 | - [How do I add classes to elements that contain an active router link?](router.md#adding-classes-to-elements-containing-active-router-links) 51 | - [How do I add optional parameters for a route?](router.md#optional-parameters) 52 | - [How do I make a breadcrumb component?](router.md#breadcrumb-component) 53 | - [How do I make router components and directives available for every component?](router.md#global-router-directives) 54 | - [How do I use regular expressions for a route?](router.md#router-regex-serializer) 55 | - [How do I dynamically configure routes](router.md#router-dynamic-config) 56 | 57 | ## [Forms](#forms-1) 58 | - [Validation](#validation) 59 | - [Multiple Validators](#how-do-i-use-more-than-one-validator-on-a-single-control) 60 | - [Custom validation](#how-do-i-make-a-custom-validator) 61 | - [Async Validators](#how-do-i-make-an-async-validator) 62 | - [Dependent Validators](#how-do-i-validate-a-control-based-on-the-value-in-another-control) 63 | - [Complex Forms](#complex-forms) 64 | - [Dependent Inputs](#how-do-i-have-a-select-box-that-is-dependent-on-another-select-box) 65 | - [Form elements in sub components](#how-do-i-have-form-elements-in-sub-components) 66 | 67 | ## Templates 68 | - [How do I make n elements in an *ngFor without a model?](https://plnkr.co/edit/FTPFoylc8s8pEiVRMoB9?p=preview) 69 | 70 | ## [Services and Components](services.md) 71 | - [How do I create a service?](services.md#how-do-i-create-a-service) 72 | - [How do I share a service instance between multiple components?](services.md#how-do-i-share-a-service-instance-between-multiple-components) 73 | - [How do I communicate between two sibling components?](services.md#how-do-i-communicate-between-two-sibling-components) 74 | - [How do I communicate between components using a shared service?](services.md#how-do-i-communicate-between-components-using-a-shared-service) 75 | 76 | ## Testing 77 | - [How do I test an error path with Http and MockBackend?](testing-http-services.md) 78 | 79 | ## [Making fun things](cool_stuff.md) 80 | - Drag and Drop 81 | - Other fun things... 82 | 83 | 84 | # Router 85 | 86 | ## Any good tutorials for the Router? 87 | Not yet, in the meantime you can look at this: https://www.youtube.com/watch?v=z1NB-HG0ZH4 88 | 89 | You can also take a look at this Plunkr, which while complex, does just about everything you would want with the router. http://plnkr.co/edit/Bim8OGO7oddxBaa26WzR?p=preview 90 | 91 | ## [How do I do breadcrumbs with the Router?](http://plnkr.co/edit/4cw2fPv3vX36v5Lu9Dnq?p=preview) 92 | 93 | ## [How do I make the Router components and directives available for every component?](http://plnkr.co/edit/FmMBasgv1rC1Qs6sJTMA?p=preview) 94 | 95 | # Forms 96 | 97 | ## Validation 98 | 99 | ### [How do I use more than one validator on a single control?](https://plnkr.co/edit/5yO4HviXD7xIgMQQ8WKs?p=preview) 100 | 101 | ### [How do I make a custom validator?](https://plnkr.co/edit/5yO4HviXD7xIgMQQ8WKs?p=preview) 102 | 103 | ### [How do I make an async validator?](http://plnkr.co/edit/vlzDapiOgVWLNqltEbGb?p=preview) 104 | 105 | ### [How do I validate a control based on the value in another control?] (http://plnkr.co/edit/NqQhBPJJo1PzHfisvh9J?p=preview) 106 | 107 | ## Complex Forms 108 | 109 | ### [How do I have a select box that is dependent on another select box](http://plnkr.co/edit/VTCKxH82XVy6XswaiKbg?p=preview) 110 | 111 | AKA: How do I make a state/province dropdown that changes contents when the country changes? 112 | 113 | ### [How do I have form elements in sub components](https://plnkr.co/edit/awfs0HGLkJOd6qdY8rhF?p=preview) 114 | -------------------------------------------------------------------------------- /angular2readiness.md: -------------------------------------------------------------------------------- 1 | # Table of Contents 2 | 3 | - [When will Angular 2 be released?](#when-will-angular-2-be-released) 4 | - [Seriously though, can I get an estimate?](#seriously-though-can-i-get-an-estimate) 5 | - [Is it ready for me?](#is-it-ready-for-me) 6 | - [Beta](#beta) 7 | - [Stability/Bugginess](#stabilitybugginess) 8 | - [Known Regressions](#known-regressions) 9 | - [API Stability](#api-stability) 10 | - [Documentation](#documentation) 11 | - [Ecosystem](#ecosystem) 12 | - [Community/Blogs/Support/Etc...](#communityblogssupportetc) 13 | - [Do I have to use Typescript?](#do-i-have-to-use-typescript) 14 | - [Do I have to use a build system? What build system should I use?](#do-i-have-to-use-a-build-system-what-build-system-should-i-use) 15 | - [Router](#router) 16 | - [Internationalization](#internationalization) 17 | - [Animation](#animation) 18 | - [Twitter Bootstrap/Material Design](#twitter-bootstrapmaterial-design) 19 | 20 | # When will Angular 2 be released? 21 | 22 | When it's ready. 23 | 24 | # Seriously though, can I get an estimate? 25 | 26 | Any estimate given will be wrong. A better question to ask might be 'is it ready for me?' 27 | 28 | # Is it ready for me? 29 | 30 | That depends. Some Google teams are already using Angular 2 in production. Let's break it down. 31 | 32 | # Beta 33 | 34 | The Angular 2 team has stated that what they have released is ready, and they hope to minimize any further breaking changes. 35 | Read the release announcement: http://angularjs.blogspot.ca/2015/12/angular-2-beta.html 36 | 37 | # Stability/Bugginess 38 | 39 | Angular 2 is very well tested~~, and does not exhibit a lot of bugs~~. Their git hub page shows compatibility for all the browsers they support, and they do benchmarks to test that they have not slowed things down. If you were to stick with a given release of Angular 2 in beta, you could go to production with it successfully. That said, there are some known regressions. 40 | 41 | ## Known Regressions 42 | 43 | Here are a number of known issues/regressions that the community has found affecting whether you could go to production with a given version of Angular 2 44 | 45 | - Since Beta 1 46 | - Attribute and class bindings throw an error when declared inside ngForm elements in Beta.1 [6374](https://github.com/angular/angular/issues/6374) 47 | - Since Beta 2 48 | - "Attempt to use a dehydrated detector" in routes, triggered by eventEmitter [#6786](https://github.com/angular/angular/issues/6786) 49 | - Since Beta 6 50 | - TypeError: viewFactory_0 is not a function [#7037](https://github.com/angular/angular/issues/7037) 51 | - Since Beta 16 52 | - Scheduler / tick not working for code with multiple async-events [#8251](https://github.com/angular/angular/issues/8251) 53 | - className property binding and "complex" expressions [#8244](https://github.com/angular/angular/issues/8244) 54 | - When injecting a non-imported class all of them are undefined [#8245](https://github.com/angular/angular/issues/8245) 55 | - ngFor + ChangeDetectionStrategy.OnPush = event handler not working [#8242](https://github.com/angular/angular/issues/8242) 56 | - UMD bundle missing ng.platform.common export [#8299](https://github.com/angular/angular/issues/8299) 57 | 58 | The currently recommended beta is the latest beta (16 at the time of this update). 59 | 60 | # API Stability 61 | 62 | With the release of beta, the Angular 2 team is hoping not to make breaking API changes. Some are likely to happen, but hopefully it should not require sweeping changes to your app. The only known proposed api breakages at this time are the router, and the animation API, as the current animation api is said to be temporary. 63 | 64 | # Documentation 65 | 66 | The general documentation and guide are very good and should be required reading. The API documentation is incomplete, and some examples are out of date. Overall the documentation is viable for everyday use. 67 | 68 | # Ecosystem 69 | 70 | The ecosystem is still just getting started. There will likely be a fair bit of work to catch up with Angular 1. That said, Angular 2 is largely free of the 'Angularisms' that made having Angular specific plugins a necessity. In many cases you can just use a vanilla js library with a thin component or directive wrapper you write yourself. 71 | 72 | # Community/Blogs/Support/Etc... 73 | 74 | The Angular 2 community is thriving, and a lot of information and tutorials can be found on the internet. The major problem is a lot of content covers the earlier alpha versions, and may not be directly applicable to the beta. The concepts are consistent from alpha to beta, and in most cases the only changes are small syntax changes. 75 | 76 | If you need support, the best place to look is the Angular 2 gitter: https://gitter.im/angular/angular. There are lots of people there who can help you out. 77 | 78 | # Do I have to use Typescript? 79 | 80 | Technically, no. You can use whatever you like. It is strongly recommended that you use TypeScript though. 81 | 82 | Documentation appears to be centered on TypeScript first, and the vast majority of examples are in it as well. Most users of Angular 2 have chosen to use Typescript, and that is what they will be familiar with. 83 | 84 | The angular team is also developing a plugin for TypeScript that will add Intellisense type hinting for Angular 2 specific constructs, for any editor that supports TypeScript integration. 85 | 86 | # Do I have to use a build system? What build system should I use? 87 | 88 | It is STRONGLY RECOMMENDED that you use a build system such as Webpack or SystemJs. 89 | 90 | Using a build system is not required or critical to the functioning of your Angular 2 app, however it is the long term plan, and to get all of the benefits of Angular 2 you will need a compile step. There are lots of bootstrap templates floating around github. Start your project with one of those and you won't have too much trouble. 91 | 92 | - Webpack Basic Starter: https://github.com/ocombe/ng2-webpack 93 | - Webpack Advanced Starter: https://github.com/AngularClass/angular2-webpack-starter 94 | - SystemJs Basic Starter: https://github.com/pkozlowski-opensource/ng2-play 95 | - SystemJs Advanced Starter: https://github.com/mgechev/angular2-seed 96 | 97 | # Router 98 | 99 | The Angular 2 router has some serious gaps at this time. Most of them have been worked around in some fashion in the Router section of this FAQ. It is stable, though there is a Proposed API change. 100 | 101 | # Internationalization 102 | 103 | As stated in the beta announcement, Internationalization is not yet complete. If you need this and are not willing to write your own internationalization module and port to the released one when it is done, Angular 2 may not be ready for you yet. 104 | 105 | # Animation 106 | 107 | Angular 2's animation module is very rudimentary and the release version is not yet ready. You will have to write your own animations, or wait. 108 | 109 | # Twitter Bootstrap/Material Design 110 | 111 | The Angular 2 specific version of Material is in alpha and available here: https://github.com/angular/material2 112 | 113 | There is not an official version of Angular 2 bootstrap, but there are some repos you can find if you search. I suggest looking at [ng-bootstrap/core](https://github.com/ng-bootstrap/core) 114 | -------------------------------------------------------------------------------- /best-practices.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | - [Proper use of EventEmitters](#proper-use-of-eventemitters) 4 | - [ElementRef, nativeElement and Renderer](#elementref-nativeelement-and-renderer) 5 | - [Don't use Subjects](#dont-use-subjects) 6 | - [Don't mix angular2 with 3rd libs](#dont-mix-angular2-with-3rd-libs) 7 | - [Don't use `ngAfterViewChecked` nor `ngAfterContentChecked`](#dont-use-ngafterviewchecked-nor-ngaftercontentchecked) 8 | - [Accessing elements in the view](#accessing-elements-in-the-view) 9 | - [Using @Injectable() in services](#using-injectable-in-services) 10 | - ~~[DynamicComponentLoader and loadAsRoot](#dynamiccomponentloader-and-loadasroot)~~ _DynamicComponentLoader has been deprecated, see [5297c9d9](https://github.com/angular/angular/commit/5297c9d9ccc6f8831d1656915e3d78e767022517)_ 11 | 12 | ## Proper use of EventEmitters 13 | 14 | While EventEmitter extends from Subject, giving us the ability to subscribe, you should not count on this staying. [Ward Bell has stated](http://www.bennadel.com/blog/3038-eventemitter-is-an-rxjs-observable-stream-in-angular-2-beta-6.htm#comments_47949) that it is highly likely to be removed before release. EventEmitter is intended to ONLY be used with `@Output()`. If you want to subscribe just use a Subject directly. 15 | 16 | See more 17 | - [What is the proper use of an EventEmitter?](http://stackoverflow.com/questions/36076700/what-is-the-proper-use-of-an-eventemitter) 18 | 19 | ## ElementRef, nativeElement and Renderer 20 | 21 | Official documentation recommends against using `nativeElement` directly. The reason for this is because it is not WebWorker safe (It may also not work with Universal, and alternate renderer implementaitons). The preferred approach is to use the `nativeElement` with the Renderer. Of course, if you don't plan on using any of the cool stuff mentioned above, and are only targeting desktop browsers, then you should feel free to do whatever works; sometimes that's the only option. 22 | 23 | Consider the following examples 24 | 25 | ```js 26 | 27 | constructor(renderer: Renderer, elementRef: ElementRef) {} 28 | 29 | 30 | // Setting an attribute 31 | this.renderer.setElementAttribute(this.elementRef.nativeElement, 'contenteditable', 'true'); 32 | 33 | // Setting a property 34 | this.renderer.setElementProperty(this.elementRef.nativeElement, 'checked', 'true'); 35 | 36 | // Setting a style 37 | this.renderer.setElementStyle(this.elementRef.nativeElement, 'background-color', 'red'); 38 | 39 | // Setting a class 40 | .my-css-class {} 41 | this.renderer.setElementClass(this.elementRef.nativeElement, 'my-css-class', true); // or false to remove 42 | 43 | // Invoking a method 44 | this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'click', []); // Click doesn't receive any parameteres 45 | this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'scrollIntoView', [false]); // 'scrollIntoView' accept true or false as parameter 46 | 47 | // Listen events in the element 48 | this.renderer.listen(this.elementRef.nativeElement, 'click', () => { /* callback */ }); 49 | 50 | // Listen to global events 51 | this.renderer.listenGlobal('document', 'click', () => { /* callback */}); 52 | 53 | ``` 54 | 55 | 56 | See more 57 | - [What are some good alternatives to accessing the DOM using nativeElement in Angular2?](http://stackoverflow.com/questions/36108995/what-are-some-good-alternatives-to-accessing-the-dom-using-nativeelement-in-angu) 58 | - [Dynamically add event listener in Angular 2](http://stackoverflow.com/questions/35080387/dynamically-add-event-listener-in-angular-2) 59 | 60 | 61 | ## Don't use Subjects 62 | 63 | Subjects are a really powerful concept, they're an Observable that can also emit events. This power is easily abused though, and as such, it is better to try and avoid using Subjects whenever possible. 64 | 65 | There is a lot of discussion on why using Subjects is a bad idea, and the intent here is merely to be a summary. If you wish to learn more about subjects and why you shouldn't use them, please see the further reading at the end of this section. 66 | 67 | The gist of it is that Subjects are uncontrolled inputs to your observable sequence. You could be expecting numbers, and get a string instead. Controlling the input to your sequence is very important. This is why whenever possible you want to use an Observable helper instead of a Subject. Subjects are also hot, meaning that subcribers will only receive new events and not historical ones. 68 | 69 | Please also keep in mind, that if you use Observable.create and then hoist the input out of the create call, you have just made a subject. 70 | 71 | ### What should I use instead? 72 | 73 | First and foremost, if you already have an Observable, or something that can easily be observed (Controls, Events, etc..) you should just observe it, and extend the processing chain to meet your needs (making it cold or hot, etc..). 74 | 75 | Once you have exhausted all of your options for Obervable.x besides create and Subject, then you must if your entire sequence can be determined at creation. If this is the case, then use Observable.create, otherwise use a Subject. 76 | 77 | Further Reading: 78 | - (http://tomstechnicalblog.blogspot.ca/2016/03/rxjava-problem-with-subjects.html) 79 | - (http://davesexton.com/blog/post/To-Use-Subject-Or-Not-To-Use-Subject.aspx) 80 | - (https://medium.com/@benlesh/learning-observable-by-building-observable-d5da57405d87#.12a0rfxtt) 81 | - (https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339#.x0q63ntrm) 82 | 83 | 84 | ## Don't mix Angular 2 with third party libraries 85 | 86 | Angular 2 works far better with third party libraries than Angular 1 did. In many cases, a library will work just fine with Angular 2. The biggest reasons not to use third party libraries is that they simply will not work optimally with Angular 2. 87 | 88 | Most javascript libraries rely on `addEventListener`, `setTimeouts` and others that trigger change detection in Angular 2. Triggering, or listening to events of 3rd party libs can trigger excesive change detection, and considerably decrease the perfomance of your application. 89 | 90 | On the other hand, these libraries can rely on event handling not patched by angular2, therefore these events will run outside angular2's zone causing change detection NOT to run! 91 | 92 | Additionally, Angular 2 wants templates to be compiled at build time, and not include the compiler in your redistributable (improving speed and load time). This means that while it is possible to use third party libraries in your templates, it is not possible to compile angular templates in your third party libs, as that would require exposing the compiler and bundling it. 93 | 94 | With all of that said, libraries that don't manipulate the dom, and don't need to be patched to work with zones can and do work perfectly with Angular 2, without patching or modification. 95 | 96 | If some cool library hasn't been ported to angular2, be the first to port it! Make yourself famous! 97 | 98 | See more 99 | - [Using JQuery With Angular 2.0](http://www.syntaxsuccess.com/viewarticle/using-jquery-with-angular-2.0) 100 | 101 | 102 | ## Don't use `ngAfterViewChecked` nor `ngAfterContentChecked` 103 | 104 | `ngAfterViewChecked` and `ngAfterContentChecked` are executed everytime change detection runs. 105 | Doing heavy calculations, adding/removing DOM or similar can end up in a very low performance application. 106 | 107 | Using Promises, setTimeouts, setIntervals, among others trigger change detection which executes these two lifecycle hooks. This combination can end in endless loops, memory leaks, etc... 108 | 109 | ## Accessing elements in the view 110 | 111 | Using `document` is discouraged, we cannot rely in it since it's not webworker safe. We [can't access the DOM within a WebWorker!](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) 112 | 113 | To access elements in the view safely we can use 114 | 115 | `@ViewChild/@ViewChildren` with local variables or types. 116 | 117 | Using local variables 118 | 119 | ```js 120 | @Component({ 121 | selector : 'my-app', 122 | template : ` 123 |
Content inside my div
124 | ` 125 | }) 126 | class MyApp { 127 | @ViewChild('myDiv') myDiv: HTMLElement; 128 | 129 | ngAfterViewInit() { 130 | // this.myDiv 131 | } 132 | } 133 | 134 | ``` 135 | 136 | Using types. Create a `@Directive` and attach it to the element 137 | 138 | ```js 139 | @Directive({ 140 | selector : 'div' 141 | }) 142 | class MyDiv {} 143 | 144 | @Component({ 145 | selector : 'my-app', 146 | template : ` 147 |
Content inside my div
148 | `, 149 | directives : [MyDiv] 150 | }) 151 | class MyApp { 152 | @ViewChild(MyDiv) myDiv: MyDiv; 153 | 154 | ngAfterViewInit() { 155 | // this.myDiv 156 | } 157 | } 158 | 159 | ``` 160 | 161 | 162 | ## Using @Injectable() in services 163 | 164 | Have you ever seen the error message `Cannot resolve all parameters for MyService(?). Make sure they all have valid type or annotations.`? Well, that's because you missed @Injectable()! Why do we need it really? 165 | 166 | >TypeScript generates metadata when the `emitDecoratorMetadata` option is set. However, that doesn’t mean that it generates metadata blindly for each and every class or method of our code. **TypeScript only generates metadata for a class, method, property or method/constructor parameter when a decorator is actually attached to that particular code**. Otherwise, a huge amount of unused metadata code would be generated, which not only affects file size, but it’d also have an impact on our application runtime. 167 | 168 | Portion extracted from [Injecting services in services in Angular 2](http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html) by Pascal Precht. 169 | 170 | Do we really need @Injectable()? Not really, we could use any annotation, the point is to emit metadata and for that we could use any of them! 171 | 172 | This would work as well 173 | 174 | ```javascript 175 | class MyService { 176 | constructor(@Inject(Http) http: Http) {} 177 | } 178 | ``` 179 | 180 | But the best practice is to use @Injectable() 181 | 182 | ```javascript 183 | @Injectable() 184 | class MyService { 185 | constructor(http: Http) {} 186 | } 187 | ``` 188 | 189 | 190 | Angular2 is promoting [using @Injectable()](https://github.com/angular/angular.io/pull/1012#issuecomment-202326319) as a best practice, so the best option is to follow their recommendations. 191 | 192 | 193 | 194 | ## DynamicComponentLoader and loadAsRoot 195 | 196 | By @gdi2290, see his [comment](https://github.com/angular/angular/issues/6223#issuecomment-193908465) 197 | >loadAsRoot is used during [bootstrap](https://github.com/angular/angular/blob/2.0.0-beta.8/modules/angular2/src/core/application_ref.ts#L50) where angular is wiring everything up (di, cd etc) and by design it doesn't wire anything up that was rendered on the server (security reasons). 198 | 199 | So basically you shouldn't use `loadAsRoot` unless you're rewriting the bootstrap logic, taking into consideration the quote above. Use `loadNextToLocation` or `loadIntoLocation` instead. 200 | -------------------------------------------------------------------------------- /cool_stuff.md: -------------------------------------------------------------------------------- 1 | - [Virtual Scrolling](http://plnkr.co/edit/HVBw0bnGYwUt6P4j6uba?p=preview) - Rob Wormald 2 | - [Angular 2 + React](http://plnkr.co/edit/Sz9OKJaBtjQJb1F1kaIU) - Rob Wormald 3 | - [Polymer + Angular 2](http://plnkr.co/edit/yh0ACeu6g5n8D7YuhJvg?p=preview) - Rob Wormald 4 | - [Http Exponential Backoff](http://plnkr.co/edit/9kQju7I9jigf6PWsEpSf?p=preview) - Rob Wormald 5 | - [Date Picker Control](https://plnkr.co/edit/Xt4MlMp2sW35YLDX0u7M?p=preview) - Rob Wormald 6 | -------------------------------------------------------------------------------- /router.md: -------------------------------------------------------------------------------- 1 | # Table Of Contents 2 | - [How do I protect routes?](#protecting-routes) 3 | - [How do I resolve data before a route activates?](#resolving-route-data) 4 | - [How do I handle invalid URLs?](#handling-invalid-urls) 5 | - [How do I add classes to elements that contain an active router link?](#adding-classes-to-elements-containing-active-router-links) 6 | - [How do I add optional parameters for a route?](#optional-parameters) 7 | - [How do I make a breadcrumb component?](#breadcrumb-component) 8 | - [How do I make router components and directives available for every component?](#global-router-directives) 9 | - [How do I use regular expressions for a route?](#router-regex-serializer) 10 | - [How do I dynamically configure routes](#router-dynamic-config) 11 | 12 | ## Protecting routes 13 | 14 | Routes are protected using the `CanActivate` decorator. Dependency Injection is not available within the CanActivate function without a workaround. 15 | 16 | http://plnkr.co/edit/SF8gsYN1SvmUbkosHjqQ?p=preview 17 | 18 | ## Resolving route data 19 | 20 | Resolving route data has not been implemented yet. As a workaround you can use the Dependency Injection workaround used with `CanActivate`, a custom router outlet, and a service to add providers for the route. 21 | 22 | http://plnkr.co/edit/SCNA0P?p=preview 23 | 24 | ## Optional parameters 25 | 26 | Any parameter that is not defined in your route `path` is considered optional and will be added to the URL as a query string parameter for top level routes or a matrix parameter for child routes. 27 | 28 | ```js 29 | @RouteConfig([ 30 | { path: '/users/:id', component: Users, name: 'Users' } 31 | ]) 32 | class AppComponent{} 33 | ``` 34 | 35 | ```html 36 | John Smith 37 | ``` 38 | 39 | ## Handling Invalid URLs 40 | 41 | This feature has not been implemented yet, but you can use a route with a wildcard parameter to redirect another route 42 | 43 | ```js 44 | @RouteConfig([ 45 | { path: '/404', component: NotFound, name: 'NotFound' }, 46 | { path: '/**', redirectTo: ['/NotFound'] } 47 | ]) 48 | class AppComponent{} 49 | ``` 50 | 51 | ## Adding classes to elements containing active router links 52 | 53 | This can be accomplished with a custom directive that finds the first `routerLink` and if it becomes active, it will add the class the element. 54 | 55 | ```js 56 | import {isPresent, isBlank} from 'angular2/src/facade/lang'; 57 | import {Directive, Input, Query, QueryList, Renderer, ElementRef} from 'angular2/core'; 58 | import {Router, RouterLink} from 'angular2/router'; 59 | 60 | @Directive({ selector: '[routerActive]' }) 61 | export class RouterActive { 62 | @Input('routerActive') activeClass; 63 | 64 | constructor( 65 | @Query(RouterLink) public routerLinks:QueryList, 66 | public element: ElementRef, 67 | public router: Router, 68 | public renderer: Renderer 69 | ) {} 70 | 71 | ngOnInit() { 72 | this.router.root.subscribe((_) => { 73 | this.checkActive(); 74 | }); 75 | } 76 | 77 | ngAfterViewInit() { 78 | if (!this.activeClass) { 79 | this.activeClass = 'router-link-active'; 80 | } 81 | 82 | this.checkActive(); 83 | } 84 | 85 | checkActive() { 86 | let active = this.routerLinks.first.isRouteActive; 87 | this.renderer.setElementClass(this.element.nativeElement, this.activeClass, active); 88 | } 89 | } 90 | ``` 91 | 92 | ```js 93 | import {Component} from 'angular2/core'; 94 | import {RouteConfig} from 'angular2/router'; 95 | import {RouterActive} from './RouterActive'; 96 | 97 | @Component({ 98 | selector: 'my-app', 99 | template: ` 100 | 110 | `, 111 | directives: [ROUTER_DIRECTIVES, RouterActive] 112 | }) 113 | @RouteConfig([ 114 | { path: '/', component: Home, name: 'Home' }, 115 | { path: '/about', component: About, name: 'About' } 116 | ]) 117 | export class AppComponent {} 118 | ``` 119 | 120 | ## Breadcrumb component 121 | 122 | http://plnkr.co/edit/4cw2fPv3vX36v5Lu9Dnq?p=preview 123 | 124 | ## Global router directives 125 | 126 | Add the router components and directives to the platform directives. This will allow you to use the `routerLink` and `router-outlet` directives without adding ROUTER_DIRECTIVES to each component. 127 | 128 | ```js 129 | import {bootstrap} from 'angular2/platform/browser'; 130 | import {App} from './app'; 131 | import {provide, PLATFORM_DIRECTIVES} from 'angular2/core'; 132 | 133 | bootstrap(App, [ 134 | provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES], multi: true}) 135 | ]); 136 | ``` 137 | 138 | ## Router regex serializer 139 | 140 | To use regular expressions for route matching, you provide a regular expression and a serializer that will return the generated url. 141 | 142 | ```js 143 | @Component({ 144 | selector: 'regex-route', 145 | template: `Regex Route` 146 | }) 147 | class RegexRoute{} 148 | 149 | @RouteConfig([ 150 | { name : 'RegexRoute', 151 | regex: '^/test/(.+)/(.+)$', // matches /test/:parama/:paramb 152 | serializer: (params) => new GeneratedUrl(`/${params.a}/${params.b}`, {}), 153 | component: RegexRoute 154 | } 155 | ]) 156 | export class App {} 157 | ``` 158 | 159 | ```html 160 | Regex Route 161 | ``` 162 | 163 | ## Router dynamic config 164 | 165 | To generate a route config dynamically, inject the router into your main app component and configure the routes . 166 | 167 | ```js 168 | import {Router} from 'angular2/router'; 169 | 170 | @Component({...}) 171 | export class AppComponent { 172 | constructor(router: Router) { 173 | let routes = []; 174 | 175 | if (someCondition) { 176 | routes = [ 177 | { path: '/', component: Home, name: 'Home' }, 178 | { path: '/about', component: About, name: 'About' } 179 | ]); 180 | } else { 181 | routes = [ 182 | { path: '/home', component: Home, name: 'Home', useAsDefault: true }, 183 | { path: '/away', component: Away, name: 'Away' } 184 | ]); 185 | } 186 | 187 | router.config(routes); 188 | } 189 | } 190 | ``` 191 | -------------------------------------------------------------------------------- /rxjs.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | - [Adding operators (map is not defined)](#adding-operatorsobservables-map-is-not-defined) 3 | - [Full RxJS](#full-rxjs) 4 | - [Individual Operators](#individual-operators) 5 | - [Loading operators individually for RxJS + Angular2 + SystemJS](#loading-operators-individually-for-rxjs--angular2--systemjs) 6 | - [Configuration for full RxJS](#configuration-for-full-rxjs) 7 | - [Configuration for individual observables / operators](#configuration-for-individual-observables--operators) 8 | - [Simpler configuration](#simpler-configuration) 9 | - [Alternative configuration](#alternative-configuration) 10 | - [Reference](#reference) 11 | - [What are observables and where can I learn more about them and RxJS?](#what-are-observables-and-where-can-i-learn-more-about-them-and-rxjs) 12 | - [Redux + Rx + Angular2 / ngrx](#redux--rx--angular2--ngrx) 13 | - [Redux](#redux) 14 | - [ngrx](#ngrx) 15 | 16 | # Adding operators/observables (map is not defined) 17 | 18 | Due to the number of operators, the size of RxJS is very large. As such, they have provided a method to trim down the size when bundling where operators are added as needed. 19 | If you are using SystemJS, some further configuration is needed beyond what is discussed in this section. See:[Loading operators individually for RxJS + Angular2 + SystemJS](#loading-operators-individually-for-rxjs--angular2--systemjs) 20 | 21 | ## Full RxJS 22 | If you want to enable the full functionality of RxJS and don't care about bundle size, you can do: 23 | ```typescript 24 | import 'rxjs/Rx'; 25 | import {Observable} from 'rxjs/Observable'; 26 | 27 | Observable.of(1,2,3); 28 | ``` 29 | or (from the RxJS docs) 30 | ```typescript 31 | import Rx from 'rxjs/Rx'; 32 | 33 | Rx.Observable.of(1,2,3) 34 | ``` 35 | ## Individual Operators 36 | If you wish to minimize your bundle size you can import individual operators and observables: 37 | ```typescript 38 | import {Observable} from 'rxjs/Observable'; 39 | // No need to specify the operator, just import and it will autopatch 40 | import 'rxjs/add/operator/map'; 41 | import 'rxjs/add/observable/from'; 42 | 43 | Observable.fromArray([1,2,3]).map(val => val+1).subscribe((d) => console.log(d)); 44 | ``` 45 | It is suggested that operators and observables be added in your bootstrap or similar to avoid isses with operators not existing when you add them in a different class from where the Observable is created. 46 | 47 | Further Reading: https://github.com/ReactiveX/RxJS#installation-and-usage 48 | 49 | # Loading operators individually for RxJS + Angular2 + SystemJS 50 | 51 | This guide assumes you have the latest version of Angular2, RxJS 5 and SystemJS. 52 | 53 | In your index.html your System.config should look like this 54 | 55 | ## Configuration for full RxJS 56 | 57 | ```javascript 58 | System.config({ 59 | map: { 60 | rxjs: 'node_modules/rxjs' 61 | }, 62 | packages: { 63 | rxjs: { defaultExtension: 'js' } 64 | } 65 | } 66 | ``` 67 | Note : this configuration is not needed if you're using the Rx.js bundle provided by angular2. See the [official plnkr](https://angular.io/resources/live-examples/tutorial/ts/plnkr.html). 68 | 69 | After you're done with this config, you can import them as in [Individual Operators](#individual-operators) 70 | 71 | ## Reference 72 | 73 | - Issue [RxJS #843](https://github.com/ReactiveX/RxJS/pull/843) 74 | - Issue [ng2 #5632](https://github.com/angular/angular/issues/5632) 75 | - Issue [ng2 #5749](https://github.com/angular/angular/issues/5749) 76 | - [plnkr with code example](http://plnkr.co/edit/jzd0SF70GBk1hrSsp4M8) 77 | 78 | 79 | # What are observables and where can I learn more about them and RxJS? 80 | 81 | - You may want to read this introduction: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 82 | - For visual examples of Rx see: [Rx Marbles](http://rxmarbles.com/) 83 | - [RxJS 4 operator documentation with examples](https://github.com/Reactive-Extensions/RxJS/tree/master/doc/api/core/operators) (applies reasonably to RxJS 5 in Angular 2) 84 | - @xgrommx put togther an awesome [rx book](http://xgrommx.github.io/rx-book/index.html) 85 | - [Filtering data using observables and form inputs](http://plnkr.co/edit/CTpE1DtaVzk1JU5eQWBu?p=preview) 86 | - [Drag and drop list (similar to JqueryUI sortable list)](http://plnkr.co/edit/LD5FJaI4OOFbKfvhjD4e?p=preview) 87 | - [Taking advantage of Observables in Angular 2](http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html) 88 | - [Taking advantage of Observables in Angular 2 - Part 2](http://blog.thoughtram.io/angular/2016/01/07/taking-advantage-of-observables-in-angular2-pt2.html) 89 | - Youtube Talks 90 | - Rob Wormald 91 | - [Everything is a Stream](https://www.youtube.com/watch?v=UHI0AzD_WfY) 92 | - [Angular 2 Data Flow - Jeff Cross, Rob Wormald and Alex Rickabaugh](https://www.youtube.com/watch?v=bVI5gGTEQ_U) 93 | - [Angular 2 Data Flow - Rob Wormald](https://vimeo.com/144625829) 94 | - Non Free resources: 95 | - https://egghead.io/series/introduction-to-reactive-programming 96 | - https://pragprog.com/book/smreactjs/reactive-programming-with-rxjs 97 | 98 | # Redux + Rx + Angular2 / ngrx 99 | 100 | I suggest you look at [ngrx](https://github.com/ngrx) before going with redux proper, as it does the same sort of job. That is not to say that redux is bad or inappropriate, but if you're not already invested you may find it easier. 101 | 102 | ## Redux 103 | - [ng2+redux guide](http://www.syntaxsuccess.com/viewarticle/redux-in-angular-2.0) (Thanks @baloodevil) 104 | - It's out of scope for this faq, but a guide for Redux in general and why it is useful: [Egghead.io getting started with redux](https://egghead.io/series/getting-started-with-redux) 105 | 106 | ## ngrx 107 | - [store](https://github.com/ngrx/store) 108 | - [store example](https://github.com/ngrx/angular2-store-example) 109 | - [refactoring underway](https://github.com/fxck/angular2-store-example/tree/fxck-refactoring) 110 | - [examples](https://github.com/btroncone/ngrx-examples) (Thanks @btroncone) 111 | - [docs from @btroncone](https://github.com/btroncone/ngrx.github.io) 112 | 113 | -------------------------------------------------------------------------------- /services.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | - [How do I create a service?](#how-do-i-create-a-service) 3 | - [How do I share a service instance between multiple components?](#how-do-i-share-a-service-instance-between-multiple-components) 4 | - [How do I communicate between two sibling components?](#how-do-i-communicate-between-two-sibling-components) 5 | - [How do I communicate between components using a shared service?](#how-do-i-communicate-between-components-using-a-shared-service) 6 | 7 | # How do I create a service? 8 | A service is just a TypeScript class. If your service has dependencies which need to be injected, you need to annotate it. The `Injectable()` annotation was created for this purpose. 9 | ```javascript 10 | export class LogService{} 11 | 12 | export class AuthService{} 13 | //This must be marked with an annotation so that Typescript will generate the information required to inject dependencies 14 | @Injectable() 15 | export class TodoService{ 16 | constructor(private logService:LogService,private authService:AuthService){} 17 | } 18 | //Provides a single instance of LogService and TodoService to TodoComponent and all of its children 19 | @Component({ 20 | providers:[LogService, TodoService] 21 | }) 22 | export class TodoComponent{ 23 | constructor(private service:TodoService){} 24 | } 25 | //Provide a single instance of AuthService to everything 26 | bootstrap(TodoComponent,[AuthService]); 27 | ``` 28 | See also: [Injectable Metadata](https://angular.io/docs/ts/latest/api/core/InjectableMetadata-class.html) 29 | 30 | # How do I share a service instance between multiple components? 31 | Provide the service in a common parent or the bootstrap. Every time you provide a service you get a new instance. 32 | 33 | # How do I communicate between two sibling components? 34 | There are two common approaches; Use a shared service, or have a common parent pass messages between the two. 35 | 36 | # How do I communicate between components using a shared service? 37 | 38 | A shared service is one way of sharing data between components which are not directly related to each other (i.e. not the immediate parent or child). 39 | 40 | [Live example](http://plnkr.co/edit/cXhr8LwWrISJWpDRLDvL?p=preview) 41 | 42 | ```typescript 43 | import {bootstrap} from 'angular2/platform/browser'; 44 | import {Component,Injectable} from 'angular2/core'; 45 | import {Subject} from 'rxjs/Subject'; 46 | 47 | /** 48 | * A shared service for displaying errors 49 | */ 50 | export class ErrorService{ 51 | latestError:Subject=new Subject(); 52 | error(err:any){ 53 | this.latestError.next(err); 54 | } 55 | 56 | } 57 | 58 | /* 59 | * Logs errors to the console. 60 | * A service which consumes the shared service and provides additional functionality. 61 | */ 62 | @Injectable() 63 | export class ErrorConsoleService{ 64 | constructor(private errorService:ErrorService){ 65 | errorService.latestError.subscribe(err=>console.log(err)); 66 | } 67 | } 68 | 69 | /* 70 | * Displays the latest error from the error service 71 | * A component which consumes the shared service 72 | */ 73 | @Component({ 74 | selector:'errors', 75 | template:`

{{service.latestError|async}}

` 76 | }) 77 | export class ErrorComponent{ 78 | constructor(private service:ErrorService){ 79 | 80 | } 81 | } 82 | 83 | /* 84 | * A form component which when submitted pushes an error to the shared service 85 | */ 86 | @Component({ 87 | selector:'formcmp', 88 | template:` 89 |
90 | 91 |
` 92 | }) 93 | export class FormComponent{ 94 | constructor(private service:ErrorService){} 95 | onSubmit() { 96 | this.service.error('form submitted'); 97 | } 98 | } 99 | 100 | /** 101 | * Root app component 102 | */ 103 | @Component({ 104 | selector:'my-app', 105 | directives:[ErrorComponent,FormComponent], 106 | template:` 107 | ` 108 | }) 109 | export class App{ 110 | //If ErrorConsoleService is not injected here, it will never be instantiated and won't work. 111 | constructor(private errConsole:ErrorConsoleService){} 112 | 113 | } 114 | bootstrap(App, [ErrorService,ErrorConsoleService]) 115 | ``` 116 | Additional documentation: http://coryrylan.com/blog/angular-2-observable-data-services 117 | -------------------------------------------------------------------------------- /testing-http-services.md: -------------------------------------------------------------------------------- 1 | 2 | [A solution from @jgongo](https://gitter.im/angular/angular?at=56a915aa80ad69394a7ad156) with some additional changes based on [comments from @krimple](https://gitter.im/angular/angular?at=56913628d739f50a36029ef7) 3 | ```typescript 4 | beforeEachProviders([ 5 | HTTP_PROVIDERS, 6 | MockBackend, 7 | provide(XHRBackend, {useClass: MockBackend}), 8 | AuthenticationService 9 | ]); 10 | 11 | 12 | it('should return an error upon unsuccessful authentication', injectAsync([XHRBackend, AuthenticationService], (mockBackend, authenticationService) => { 13 | return new Promise((resolve, reject) => { 14 | mockBackend.connections.subscribe((connection: MockConnection) => { 15 | connection.readyState = ReadyState.Done; 16 | connection.response.error(new Response(new ResponseOptions({ 17 | body: {error: 'invalid_grant', error_description: 'Incorrect username and / or password'}, 18 | status: 400 19 | }))); 20 | }); 21 | 22 | authenticationService.authenticate({username: 'john.doe', password: '12345'}).subscribe( 23 | (oauthTokenResponse) => { 24 | reject(Error('Unexpected successful response')); 25 | }, 26 | (error: Response) => { 27 | expect(error.status).toBe(400); 28 | expect(error.json().error).toBe('invalid_grant'); 29 | expect(error.json().error_description).toBe('Incorrect username and / or password'); 30 | } 31 | ); 32 | }); 33 | })); 34 | ``` 35 | --------------------------------------------------------------------------------