Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/fetis/30-seconds-of-angular

Curated collection of Angular snippets that you can understand in 30 seconds or less
https://github.com/fetis/30-seconds-of-angular

List: 30-seconds-of-angular

angular awesome-list javascript learn-to-code learning-resources programming snippets snippets-collection

Last synced: about 1 month ago
JSON representation

Curated collection of Angular snippets that you can understand in 30 seconds or less

Awesome Lists containing this project

README

        

[![Logo 30 Seconds of Angular](/builder/public/img/logo.png)](https://github.com/nycJSorg/30-seconds-of-angular)

[![Build Status](https://travis-ci.com/30-seconds/30-seconds-of-angular.svg?branch=master)](https://travis-ci.com/nycJSorg/30-seconds-of-angular) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)

> Curated collection of useful Angular snippets that you can understand in 30 seconds or less.

* Use Ctrl + F or command + F to search for a snippet.
* Snippets are written in Angular 8+.

# 30 Seconds of Angular

## Table of contents

Beginner snippets

* [Accessing Enums in template](#accessing-enums-in-template)
* [Cheat Sheets and Checklists](#cheat-sheets-and-checklists)
* [Component State Debugging](#component-state-debugging)
* [Default ViewEncapsulation value](#default-viewencapsulation-value)
* [hammerjs-gestures](#hammerjs-gestures)
* [Loader Component](#loader-component)
* [ng-content](#ng-content)
* [ngIf else](#ngif-else)
* [Optional parameters in the middle](#optional-parameters-in-the-middle)
* [Renaming inputs and outputs](#renaming-inputs-and-outputs)
* [Safe Navigation Operator](#safe-navigation-operator)
* [trackBy in for loops](#trackby-in-for-loops)
* [Understanding Microsyntax](#understanding-microsyntax)

Intermediate snippets

* [Accessing all nested form controls](#accessing-all-nested-form-controls)
* [Adding keyboard shortcuts to elements](#adding-keyboard-shortcuts-to-elements)
* [Bind to host properties with host binding](#bind-to-host-properties-with-host-binding)
* [Component level providers](#component-level-providers)
* [Global event listeners](#global-event-listeners)
* [Injecting document](#injecting-document)
* [Mark reactive fields as touched](#mark-reactive-fields-as-touched)
* [Observables as outputs](#observables-as-outputs)
* [Passing template as an input](#passing-template-as-an-input)
* [Preseving whitespaces](#preseving-whitespaces)
* [Reusing code in template](#reusing-code-in-template)
* [Reusing existing custom pipes](#reusing-existing-custom-pipes)
* [Style bindings](#style-bindings)
* [Two-way binding any property](#two-way-binding-any-property)
* [Using APP_INITIALIZER to delay app start](#using-app_initializer-to-delay-app-start)
* [Window Location injection](#window-location-injection)

Advanced snippets

* [Getting components of different types with ViewChild](#getting-components-of-different-types-with-viewchild)
* [Router Custom Preloading](#router-custom-preloading)
* [SVG](#svg)

## Beginner snippets

### Accessing Enums in template
Enums are great but they are not visible in Angular templates by default.
With this little trick you can make them accessible.

```typescript
enum Animals {
DOG,
CAT,
DOLPHIN
}

@Component({
...
})
export class AppComponent {
animalsEnum: typeof Animals = Animals;
}
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/accessing-enums-in-template) | [⬆ Back to top](#table-of-contents) | tags: [enums](https://30.codelab.fun/tags/enums) [templates](https://30.codelab.fun/tags/templates)



### Cheat Sheets and Checklists
Check out [Angular Cheat Sheet](https://angular.io/guide/cheatsheet) or ([alternative version](https://malcoded.com/angular-cheat-sheet)) containing lots of useful information condensed in one place.

Also [Angular Checklist](https://angular-checklist.io) contains is curated list of common mistakes made when developing Angular applications.

#### Links
https://malcoded.com/angular-cheat-sheet/,https://angular.io/guide/cheatsheet,https://angular.io/guide/styleguide


[⭐ Interactive demo of this snippet](https://30.codelab.fun/cheat-sheets-and-checklists) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [cheat sheet](https://30.codelab.fun/tags/cheat-sheet)



### Component State Debugging
Debug the component state in the browser console by running:
```typescript
ng.probe($0).componentInstance
```

> `$0` - is the DOM node currently selected in dev tools (`$1` for the previous one and so on).

Bonus

With Ivy renderer engine:
```typescript
ng.getComponent($0)
```

#### Links
https://blog.angularindepth.com/everything-you-need-to-know-about-debugging-angular-applications-d308ed8a51b4


[⭐ Interactive demo of this snippet](https://30.codelab.fun/component-state-debugging) | [⬆ Back to top](#table-of-contents) | tags: [good-to-know](https://30.codelab.fun/tags/good-to-know) [tips](https://30.codelab.fun/tags/tips)



### Default ViewEncapsulation value
If you're using `ViewEncapsulation` value which is different than default, it might be daunting to set the value manually for every component.

Luckily you can configure it globally when bootstrapping your app:

```TypeScript
platformBrowserDynamic().bootstrapModule(AppModule, [
{
// NOTE: Use ViewEncapsulation.None only if you know what you're doing.
defaultEncapsulation: ViewEncapsulation.None
}
]);
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/default-viewencapsulation-value) | [⬆ Back to top](#table-of-contents) | tags: [configuration](https://30.codelab.fun/tags/configuration) [styling](https://30.codelab.fun/tags/styling)



### hammerjs-gestures
To act upon swipes, pans, and pinhces as well as the other mobile gestures, you can use `hammerjs` with `HostListener` decorator, or an event binding,

```bash
npm install hammerjs
```

```typescript
@HostListener('swiperight')
public swiperight(): void {
// Run code when a user swipes to the right
}
```

Bonus

Here are samples on how to use all of the `hammerjs` event bindings, you can use these events with a `HostListener` as well:

```HTML






























```

#### Links
https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/events/hammer_gestures.ts,http://hammerjs.github.io/api/#hammer.manager,https://angular.io/api/platform-browser/HammerGestureConfig


[⭐ Interactive demo of this snippet](https://30.codelab.fun/hammerjs-gestures) | [⬆ Back to top](#table-of-contents) | tags: [good-to-know](https://30.codelab.fun/tags/good-to-know) [tips](https://30.codelab.fun/tags/tips) [components](https://30.codelab.fun/tags/components) [gestures](https://30.codelab.fun/tags/gestures)



### Loader Component
You can create own helper component and use it instead of `*ngIf`.

```typescript
@Component({
selector: 'loader',
template: `

🕚 Wait 10 seconds!
`
})
class LoaderComponent {
@Input() loading: boolean;
}
```

For usage example:
```html
🦊 🦄 🐉
```

> Note that the content will be eagerly evaluated, e.g. in the snippet below `destroy-the-world` will be created before the loading even starts:

```html

```

#### Links
https://medium.com/claritydesignsystem/ng-content-the-hidden-docs-96a29d70d11b,https://blog.angularindepth.com/https-medium-com-thomasburleson-animated-ghosts-bfc045a51fba


[⭐ Interactive demo of this snippet](https://30.codelab.fun/loader-component) | [⬆ Back to top](#table-of-contents) | tags: [tips](https://30.codelab.fun/tags/tips) [good-to-know](https://30.codelab.fun/tags/good-to-know) [components](https://30.codelab.fun/tags/components) [templates](https://30.codelab.fun/tags/templates)



### ng-content
With `ng-content` you can pass any elements to a component.
This simplifies creating reusable components.

```typescript
@Component({
selector: 'wrapper',
template: `




`,
})
export class Wrapper {}
```

```html

Hello World!

```

#### Links
https://medium.com/p/96a29d70d11b


[⭐ Interactive demo of this snippet](https://30.codelab.fun/ng-content) | [⬆ Back to top](#table-of-contents) | tags: [good-to-know](https://30.codelab.fun/tags/good-to-know) [tips](https://30.codelab.fun/tags/tips) [components](https://30.codelab.fun/tags/components)



### ngIf else
`*ngIf` directive also supports `else` statement.

```html

loading...

not loading
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/ngif-else) | [⬆ Back to top](#table-of-contents) | tags: [ngif](https://30.codelab.fun/tags/ngif) [templates](https://30.codelab.fun/tags/templates)



### Optional parameters in the middle
Navigate with matrix params:

the router will navigate to `/first;name=foo/details`
```html

link with params

```

#### Links
https://stackblitz.com/edit/angular-xvy5pd


[⭐ Interactive demo of this snippet](https://30.codelab.fun/optional-parameters-in-the-middle) | [⬆ Back to top](#table-of-contents) | tags: [routing](https://30.codelab.fun/tags/routing)



### Renaming inputs and outputs
In certain cases `@Input` and `@Output` properties can be named differently than the actual inputs and outputs.

```html



```

```typescript
@Directive({ selector: '[pagination]'})
class PaginationComponent {
@Input('paginationShowFirst')
showFirst: boolean = true;

@Output('paginationPageChanged')
pageChanged = new EventEmitter();
}
```
> Note: Use this wisely, see [StyleGuide recommedation](https://angular.io/guide/styleguide#style-05-13)

#### Links
https://angular.io/guide/styleguide#style-05-13


[⭐ Interactive demo of this snippet](https://30.codelab.fun/renaming-inputs-and-outputs) | [⬆ Back to top](#table-of-contents) | tags: [components](https://30.codelab.fun/tags/components) [templates](https://30.codelab.fun/tags/templates)



### Safe Navigation Operator
The [Safe Navigation Operator](https://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths) helps with preventing null-reference exceptions in component template expressions. It returns object property value if it exists or null otherwise.

```html

I will work even if student is null or undefined: {{student?.name}}


```

Bonus

```html
{{a?.b?.c}}
```
Underneath will be compiled to.
```html
(_co.a == null)? null: ((_co.a.b == null)? null: _co.a.b.c));
```

#### Links
https://github.com/angular/angular/issues/791


[⭐ Interactive demo of this snippet](https://30.codelab.fun/safe-navigation-operator) | [⬆ Back to top](#table-of-contents) | tags: [object property handling](https://30.codelab.fun/tags/object-property-handling) [tips](https://30.codelab.fun/tags/tips) [good to know](https://30.codelab.fun/tags/good-to-know)



### trackBy in for loops
To avoid the expensive operations, we can help Angular to track which items added or removed i.e. customize the default tracking algorithm by providing a trackBy option to NgForOf.

So you can provide your custom trackBy function that will return unique identifier for each iterated item.
For example, some key value of the item. If this key value matches the previous one, then Angular won't detect changes.

**trackBy** takes a function that has _index_ and _item_ args.

```typescript
@Component({
selector: 'my-app',
template: `


  • {{item.id}}


`
})
export class AppComponent {
trackByFn(index, item) {
return item.id;
}
}
```
If trackBy is given, Angular tracks changes by the return value of the function.

Now when you change the collection, Angular can track which items have been added or removed according to the unique identifier and create/destroy only changed items.

#### Links
https://angular.io/api/common/NgForOf,https://angular.io/api/core/TrackByFunction


[⭐ Interactive demo of this snippet](https://30.codelab.fun/trackby-in-for-loops) | [⬆ Back to top](#table-of-contents) | tags: [good-to-know](https://30.codelab.fun/tags/good-to-know) [tips](https://30.codelab.fun/tags/tips) [components](https://30.codelab.fun/tags/components) [performance](https://30.codelab.fun/tags/performance)



### Understanding Microsyntax
Under the hood Angular compiles structural directives into ng-template elements, e.g.:

```html

```

The value passed to *ngFor directive is written using microsyntax. You can learn about it [in the docs](https://angular.io/guide/structural-directives#microsyntax).

Also check out an [interactive tool](https://alexzuza.github.io/ng-structural-directive-expander/) that shows the expansion by [Alexey Zuev](https://twitter.com/yurzui)

#### Links
https://angular.io/guide/structural-directives#microsyntax,https://alexzuza.github.io/ng-structural-directive-expander/,https://angular.io/guide/structural-directives#inside-ngfor


[⭐ Interactive demo of this snippet](https://30.codelab.fun/understanding-microsyntax) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [structural directive](https://30.codelab.fun/tags/structural-directive) [microsyntax](https://30.codelab.fun/tags/microsyntax)


## Intermediate snippets

### Accessing all nested form controls
Sometimes we need to work with every single Control is a form. Here's how it can be done:

```typescript
function flattenControls(form: AbstractControl): AbstractControl[] {
let extracted: AbstractControl[] = [ form ];
if (form instanceof FormArray || form instanceof FormGroup) {
const children = Object.values(form.controls).map(flattenControls);
extracted = extracted.concat(...children);
}
return extracted;
}
```

For examples use:
```typescript
// returns all dirty abstract controls
flattenControls(form).filter((control) => control.dirty);

// mark all controls as touched
flattenControls(form).forEach((control) =>
control.markAsTouched({ onlySelf: true }));
```

#### Links
https://angular.io/guide/reactive-forms


[⭐ Interactive demo of this snippet](https://30.codelab.fun/accessing-all-nested-form-controls) | [⬆ Back to top](#table-of-contents) | tags: [reactive forms](https://30.codelab.fun/tags/reactive-forms) [tips](https://30.codelab.fun/tags/tips) [good to know](https://30.codelab.fun/tags/good-to-know)



### Adding keyboard shortcuts to elements
It's really easy to add keyboard shortcuts in the template:
```html

```

Bonus

```html

```

#### Links
https://alligator.io/angular/binding-keyup-keydown-events


[⭐ Interactive demo of this snippet](https://30.codelab.fun/adding-keyboard-shortcuts-to-elements) | [⬆ Back to top](#table-of-contents) | tags: [tips](https://30.codelab.fun/tags/tips) [good-to-know](https://30.codelab.fun/tags/good-to-know)



### Bind to host properties with host binding
Every rendered angular component is wrapped in a host element (which is the same as component's selector).

It is possible to bind properties and attributes of host element using @HostBinding decorators, e.g.

```typescript
import { Component, HostBinding } from '@angular/core';

@Component({
selector: 'my-app',
template: `

Use the input below to select host background-color:


`,
styles: [
`:host { display: block; height: 100px; }`
]
})
export class AppComponent {
@HostBinding('style.background') color = '#ff9900';
}
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/bind-to-host-properties-with-host-binding) | [⬆ Back to top](#table-of-contents) | tags: [components](https://30.codelab.fun/tags/components)



### Component level providers
Generally we get one service instance per the whole application.
It is also possible to create an instance of service per component or directive.

```typescript
@Component({
selector: 'provide',
template: '',
providers: [ Service ]
})
export class ProvideComponent {}
```

```typescript
@Directive({
selector: '[provide]',
providers: [ Service ]
})
export class ProvideDirective {}
```

#### Links
https://angular.io/guide/hierarchical-dependency-injection#component-level-injectors,https://stackblitz.com/edit/angular-cdk-happy-animals


[⭐ Interactive demo of this snippet](https://30.codelab.fun/component-level-providers) | [⬆ Back to top](#table-of-contents) | tags: [tips](https://30.codelab.fun/tags/tips) [components](https://30.codelab.fun/tags/components) [dependency-injection](https://30.codelab.fun/tags/dependency-injection)



### Global event listeners
It is possible to add global event listeners in your Components/Directives with `HostListener`. Angular will take care of unsubscribing once your directive is destroyed.

```typescript
@Directive({
selector: '[rightClicker]'
})
export class ShortcutsDirective {
@HostListener('window:keydown.ArrowRight')
doImportantThings() {
console.log('You pressed right');
}
}
```

Bonus

You can have multiple bindings:

```typescript
@HostListener('window:keydown.ArrowRight')
@HostListener('window:keydown.PageDown')
next() {
console.log('Next')
}
```

You can also pass params:

```typescript
@HostListener('window:keydown.ArrowRight', '$event.target')
next(target) {
console.log('Pressed right on this element: ' + target)
}
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/global-event-listeners) | [⬆ Back to top](#table-of-contents) | tags: [events](https://30.codelab.fun/tags/events) [components](https://30.codelab.fun/tags/components)



### Injecting document
Sometimes you need to get access to global `document`.

To simplify unit-testing, Angular provides it through dependency injection:

```typescript
import { DOCUMENT } from '@angular/common';
import { Inject } from '@angular/core';

@Component({
selector: 'my-app',
template: `

Edit me

`
})
export class AppComponent {

constructor(@Inject(DOCUMENT) private document: Document) {
// Word with document.location, or other things here....
}
}
```

#### Links
https://angular.io/api/common/DOCUMENT


[⭐ Interactive demo of this snippet](https://30.codelab.fun/injecting-document) | [⬆ Back to top](#table-of-contents) | tags: [dependency injection](https://30.codelab.fun/tags/dependency-injection)



### Mark reactive fields as touched
Here is the way to notify user that there are fields with non-valid values.

`markFieldsAsTouched` function FormGroup or FormArray as an argument.

```typescript
function markFieldsAsTouched(form: AbstractControl): void {
form.markAsTouched({ onlySelf: true });
if (form instanceof FormArray || form instanceof FormGroup) {
Object.values(form.controls).forEach(markFieldsAsTouched);
}
}
```

Bonus

It's very useful to check out more general method [Accessing all nested form controls](#accessing-all-nested-form-controls) by [Thekiba](https://twitter.com/thekiba_io) to work with controls.

#### Links
https://angular.io/guide/reactive-forms


[⭐ Interactive demo of this snippet](https://30.codelab.fun/mark-reactive-fields-as-touched) | [⬆ Back to top](#table-of-contents) | tags: [reactive forms validation](https://30.codelab.fun/tags/reactive-forms-validation) [tips](https://30.codelab.fun/tags/tips) [good to know](https://30.codelab.fun/tags/good-to-know)



### Observables as outputs
`EventEmitters` used for `@Output`'s are just Observables with an emit method.

This means that you can just use `Observable` instance instead, e.g. we can wire up FormControl value changes directly:

```TypeScript
readonly checkbox = new FormControl();
@Output() readonly change = this.checkbox.valueChanges;
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/observables-as-outputs) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [outputs](https://30.codelab.fun/tags/outputs)



### Passing template as an input
It's possible to take a template as `@Input` for a component to customize the render

```typescript
@Component({
template: `



`,
})
export class SiteMenuComponent {
@Input() template: TemplateRef;
}
```
```html

item1

item2

```
> Note: `ng-content` should be used for most of the cases and it's simpler and more declarative.
> Only use this approach if you need extra flexibility that can't be achieved with ng-content.

#### Links
https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet


[⭐ Interactive demo of this snippet](https://30.codelab.fun/passing-template-as-an-input) | [⬆ Back to top](#table-of-contents) | tags: [template](https://30.codelab.fun/tags/template)



### Preseving whitespaces
By default Angular strips all whitespaces in templates to save bytes. Generally it's safe.

For rare cases when you need to preserve spaces you can use special `ngPreserveWhitespaces` attribute:

```html


(___()'`;
/, /`
jgs \\"--\\

```

> You can also use [preserveWhitespaces](https://angular.io/api/core/Component#preserveWhitespaces) option on a component.

#### Links
https://twitter.com/mgechev/status/1108913389277839360


[⭐ Interactive demo of this snippet](https://30.codelab.fun/preseving-whitespaces) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip)



### Reusing code in template
While the best way of reusing your code is creating a component, it's also possible to do it in a template.

To do this you can use `ng-template` along with `*ngTemplateOutlet` directive.

```html



Hello {{name}}!

```

#### Links
https://angular.io/api/common/NgTemplateOutlet,https://angular.io/guide/structural-directives#the-ng-template


[⭐ Interactive demo of this snippet](https://30.codelab.fun/reusing-code-in-template) | [⬆ Back to top](#table-of-contents) | tags: [templates](https://30.codelab.fun/tags/templates)



### Reusing existing custom pipes
If you need a custom `pipe`, before creating one, consider checking out the [NGX Pipes package](https://github.com/danrevah/ngx-pipes) which has 70+ already implemeted custom pipes.

Here are some examples:

```html

{{ date | timeAgo }}

{{ 'foo bar' | ucfirst }}

3 {{ 'Painting' | makePluralString: 3 }}

{{ [1, 2, 3, 1, 2, 3] | max }}

```

#### Links
https://github.com/danrevah/ngx-pipes


[⭐ Interactive demo of this snippet](https://30.codelab.fun/reusing-existing-custom-pipes) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [pipes](https://30.codelab.fun/tags/pipes) [library](https://30.codelab.fun/tags/library)



### Style bindings
You can use advanced property bindings to set specific style values based on component property values:

```html


I am in green background


May be important text.


```

Bonus

```html

...


```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/style-bindings) | [⬆ Back to top](#table-of-contents) | tags: [styles](https://30.codelab.fun/tags/styles)



### Two-way binding any property
Similar to how you can two-way bind `[(ngModel)]` you can two-way bind custom property on a component, for example `[(value)]`. To do it use appropriate Input/Output naming:

```typescript
@Component({
selector: 'super-input',
template: `...`,
})
export class AppComponent {
@Input() value: string;
@Output() valueChange = new EventEmitter();
}
```

Then you can use it as:
```html

```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/two-way-binding-any-property) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [binding](https://30.codelab.fun/tags/binding)



### Using APP_INITIALIZER to delay app start
It is possible to execute asynchronous task before the app start by providing a function returning promise using `APP_INITIALIZER` token.

```typescript
@NgModule({
providers: [
{
provide: APP_INITIALIZER,
useValue: functionReturningPromise
multi: true
},
})
export class AppModule {}

```

#### Links
https://hackernoon.com/hook-into-angular-initialization-process-add41a6b7e,https://angular.io/api/core/APP_INITIALIZER


[⭐ Interactive demo of this snippet](https://30.codelab.fun/using-app_initializer-to-delay-app-start) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip)



### Window Location injection
For testing purposes you might want to inject `window.location` object in your component.
You can achieve this with custom `InjectionToken` mechanism provided by Angular.

```typescript
export const LOCATION_TOKEN = new InjectionToken('Window location object');

@NgModule({
providers: [
{ provide: LOCATION_TOKEN, useValue: window.location }
]
})
export class SharedModule {}

//...

@Component({
})
export class AppComponent {
constructor(
@Inject(LOCATION_TOKEN) public location: Location
) {}
}
```

#### Links
https://itnext.io/testing-browser-window-location-in-angular-application-e4e8388508ff,https://angular.io/guide/dependency-injection


[⭐ Interactive demo of this snippet](https://30.codelab.fun/window-location-injection) | [⬆ Back to top](#table-of-contents) | tags: [dependency-injection](https://30.codelab.fun/tags/dependency-injection) [testing](https://30.codelab.fun/tags/testing)


## Advanced snippets

### Getting components of different types with ViewChild
It's possible to use `@ViewChild` (also `@ViewChildren` and `@ContentChild/Children`) to query for components of different types using dependency injection.

In the example below we can use `@ViewChildren(Base)` to get instances of `Foo` and `Bar`.

```typescript
abstract class Base {}

@Component({
selector: 'foo',
providers: [{ provide: Base, useExisting: Foo }]
})
class Foo extends Base {}

@Component({
selector: 'bar',
providers: [{ provide: Base, useExisting: Bar }]
})
class Bar extends Base {}

// Now we can require both types of components using Base.
@Component({ template: `` })
class AppComponent {
@ViewChildren(Base) components: QueryList;
}
```

#### Links
https://www.youtube.com/watch?v=PRRgo6F0cjs


[⭐ Interactive demo of this snippet](https://30.codelab.fun/getting-components-of-different-types-with-viewchild) | [⬆ Back to top](#table-of-contents) | tags: [good-to-know](https://30.codelab.fun/tags/good-to-know) [tips](https://30.codelab.fun/tags/tips) [components](https://30.codelab.fun/tags/components) [dependency-injection](https://30.codelab.fun/tags/dependency-injection)



### Router Custom Preloading
Angular allows us to control the way module preloading is handled.

There are 2 strategies provided by **@angular/router**: `PreloadAllModules` and `NoPreloading`. The latter enabled by default, only preloading lazy modules on demand.

We can override this behavior by providing custom preloading strategy: In the example below we preload all included modules if the connection is good.

```typescript
import { Observable, of } from 'rxjs';

export class CustomPreloading implements PreloadingStrategy {
public preload(route: Route, load: () => Observable): Observable {
return preloadingConnection() ? load() : of(null);
}
}

const routing: ModuleWithProviders = RouterModule.forRoot(routes, {
preloadingStrategy: CustomPreloading
});
```
> Note that that the example above would not be very efficient for larger apps, as it'll preload all the modules.

#### Links
https://angular.io/api/router/PreloadingStrategy,https://vsavkin.com/angular-router-preloading-modules-ba3c75e424cb,https://medium.com/@adrianfaciu/custom-preloading-strategy-for-angular-modules-b3b5c873681a,https://coryrylan.com/blog/custom-preloading-and-lazy-loading-strategies-with-angular


[⭐ Interactive demo of this snippet](https://30.codelab.fun/router-custom-preloading) | [⬆ Back to top](#table-of-contents) | tags: [router](https://30.codelab.fun/tags/router)



### SVG
It is possible to use SVG tags in your Angular component, to create beautiful graphs and visualizations. There are 3 things you need to know:

1. When binding an SVG attribute, use `attr`
```html

```

2. When creating sub-components, use attribute and not tag selector:
```html
// Not:

```
```typescript
@Component({selector: '[child-component]' })
```

3. When using SVG tags in sub-components use svg prefix:
```typescript
@Component({
selector: '[child-component]',
template: ``
})
```


[⭐ Interactive demo of this snippet](https://30.codelab.fun/svg) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [SVG](https://30.codelab.fun/tags/svg)