Modules serve 2 main functions:
-* Defining entry points for pages
* Importing and exporting dependencies.
+* Defining routes and entry points for pages
== Modules ==
------------------------------------------------------------------------
@NgModule({
declarations: [
- // List of components declared by this module.
- // Every component used must be declared exactly once!
+ // List of components declared by this module. Every component used
+ // must be declared exactly once throughout the entire application
+ // including lazy-loaded modules!
],
imports: [
- // List of imported modules.
- // These modules may be needed by the current module
- // or simply imported so they can be re-exported (below).
+ // List of imported modules. These modules may be needed by the
+ // current module or imported so they can be re-exported (below).
],
exports: [
// List of components and modules made implicitly
providers: [
// List of services available to this module and any
// module that imports this module.
+ // NOTE: @Injectable({providedIn: 'root'}) are globally provided
+ // and share a single execution context.
]
})
------------------------------------------------------------------------
-== Component Declaration Hierarchy ==
+== Data Flow ==
-Easy mistake to make!
-Especially with lazy-loaded components. You don't know it's a
-problem until you've loaded the conflicting component.
+== Data Flow: Passing Static Strings To Components ==
-Module Foo declares Component SomeCompent.
-Module Bar wants to use Component SomeCompent.
-Module Bar cannot also declare SomeComponent.
+[source,html]
+----------------------------------------------------------------------
+<my-component someAttr="stringValue"></my-component>
+----------------------------------------------------------------------
-Module Bar must import Module Foo.
-OR SomeComp is declared in a new shared module that is imported
-by both Foo and Bar.
+[source,js]
+----------------------------------------------------------------------
+@Input() someAttr: string;
+----------------------------------------------------------------------
-== Templates ==
+== Data Flow: Passing Dynamic Values To Components ==
-*ngFor *ngIf
-<ng-template>
-<ng-container>
+[source,html]
+----------------------------------------------------------------------
+<my-component [someAttr]="someVar"></my-component>
+----------------------------------------------------------------------
-== Template Variables ==
+* Read Once
-<foo-component #myComp>
-</foo-component>
+[source,js]
+----------------------------------------------------------------------
+@Input() someAttr: string;
+----------------------------------------------------------------------
-== Components: Passing Input ==
+* Respond to Value Changes
-foo=
-[foo]=
-(foo)=
-[(foo)]=
+[source,js]
+----------------------------------------------------------------------
+_someAttr: string;
+@Input() set someAttr(a: string) {
+ this._someAttr = string;
+}
+----------------------------------------------------------------------
-// in the code
-myComp.foo = 'hello';
-myComp.foo('hello');
+== Data Flow: Passing Dynamic Values To/From Components ==
-== Components: Reading Input ==
+This is most like AngularJS 'ng-model="someVar"';
-@Input() foo: string;
-@Input() set foo(s: string) {
- this.foo_ = s;
-}
+[source,html]
+----------------------------------------------------------------------
+<my-component [(ngModel)]="someVar"></my-component>
+----------------------------------------------------------------------
-== Components: Passing Output ==
+NOTE: custom components typically don't implement [(ngModel)] but
+instead use a combination of input and output channels.
-@Output foo: EventEmitter<bool>;
-== Components: Reading Output ==
+== Data Flow: Responding to Component Events ==
-// in the template
-(foo)="myBool=$event"
-(foo)="handleFoo($event)"
+[source,html]
+----------------------------------------------------------------------
+<my-component (someAttr)="someHandler($event, ...)"></my-component>
+<my-component (someAttr)="myVar=$event"></my-component>
+----------------------------------------------------------------------
-// in the code
-myComp.foo.subscribe(b => myBool=b);
+* Component
+
+[source,js]
+----------------------------------------------------------------------
+@Output someAttr: EventEmitter<string>;
+// ...
+this.someAttr = new EventEmitter<string>();
+// ...
+this.someAttr.emit('Hello World');
+----------------------------------------------------------------------
+
+* Caller can also listen for events in the code
+[source,js]
+----------------------------------------------------------------------
+myComponentRef.someAttr.subscribe(s => this.myVar = s);
+----------------------------------------------------------------------
+
+== Templates / Syntax ==
+
+[source,html]
+----------------------------------------------------------------------
+
+*ngFor
+*ngIf
-== Components: Programmatic Control ==
+<ng-template>
+ <!-- Pre-compiled template executed on demand -->
+</ng-template>
+
+<ng-container>
+ <!-- No-Op container, good for combingin with ngFor/ngIf -->
+</ng-container>
+----------------------------------------------------------------------
-@ViewChild('')...
+== Template Variables ==
-Ref is set to null if the child component is destroyed
+[source,html]
+----------------------------------------------------------------------
+<ng-template #myTemplate>
+</ng-template>
+
+<foo-component #myComponent template="myTemplate">
+</foo-component>
+----------------------------------------------------------------------
+
+[source,js]
+----------------------------------------------------------------------
+componentRef = @ViewChild('myComponent');
+componentRef.doSomething();
+----------------------------------------------------------------------
+
+// in the code
+myComp.foo.subscribe(b => myBool=b);
-== keyboard actions ==
+== keyboard actions, neat ==
(keyup.enter)="submit()"
value of .pipe(tap(...))
-== Groking route data ==
+== Routing ==
The route API is complex, but expressive.