Skip to content

Commit 2a0e128

Browse files
committed
Merge branch 'master' into beta_logo
2 parents ec9b55e + e4562b9 commit 2a0e128

File tree

12 files changed

+237
-70
lines changed

12 files changed

+237
-70
lines changed

README.md

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,15 @@ Intermediate snippets
3333
Beginner snippets
3434

3535
* [Accessing Enums in template](#accessing-enums-in-template)
36+
* [Angular cheat sheet](#angular-cheat-sheet)
3637
* [Default ViewEncapsulation value](#default-viewencapsulation-value)
38+
* [hammerjs-gestures](#hammerjs-gestures)
3739
* [Loader Component](#loader-component)
3840
* [ng-content](#ng-content)
3941
* [ngIf else](#ngif-else)
4042
* [Optional parameters in the middle](#optional-parameters-in-the-middle)
4143
* [Renaming inputs and outputs](#renaming-inputs-and-outputs)
44+
* [Safe Navigation Operator](#safe-navigation-operator)
4245
* [trackBy in for loops](#trackby-in-for-loops)
4346
* [Understanding Microsyntax](#understanding-microsyntax)
4447

@@ -69,10 +72,10 @@ function flattenControls(form: AbstractControl): AbstractControl[] {
6972
For examples use:
7073
```typescript
7174
// returns all dirty abstract controls
72-
extractControls(form).filter((control) => control.dirty);
75+
flattenControls(form).filter((control) => control.dirty);
7376

7477
// mark all controls as touched
75-
extractControls(form).forEach((control) =>
78+
flattenControls(form).forEach((control) =>
7679
control.markAsTouched({ onlySelf: true }));
7780
```
7881

@@ -456,6 +459,17 @@ export class AppComponent {
456459

457460
<br>[⭐ 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)
458461
<br><br>
462+
### Angular cheat sheet
463+
Check out [Angular Cheat Sheet](https://angular.io/guide/cheatsheet) which contains lots of useful information condensed in one place.
464+
465+
There's also an [alternative version](https://malcoded.com/angular-cheat-sheet).
466+
467+
468+
#### Links
469+
https://malcoded.com/angular-cheat-sheet/,https://angular.io/guide/cheatsheet,https://angular.io/guide/styleguide
470+
471+
<br>[⭐ Interactive demo of this snippet](https://30.codelab.fun/angular-cheat-sheet) | [⬆ Back to top](#table-of-contents) | tags: [tip](https://30.codelab.fun/tags/tip) [cheat sheet](https://30.codelab.fun/tags/cheat-sheet)
472+
<br><br>
459473
### Default ViewEncapsulation value
460474
If you're using `ViewEncapsulation` value which is different than default, it might be daunting to set the value manually for every component.
461475

@@ -474,6 +488,74 @@ platformBrowserDynamic().bootstrapModule(AppModule, [
474488

475489
<br>[⭐ 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)
476490
<br><br>
491+
### hammerjs-gestures
492+
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,
493+
494+
```bash
495+
npm install hammerjs
496+
```
497+
498+
```typescript
499+
@HostListener('swiperight')
500+
public swiperight(): void {
501+
// Run code when a user swipes to the right
502+
}
503+
```
504+
505+
<details>
506+
<summary>Bonus</summary>
507+
508+
Here are samples on how to use all of the `hammerjs` event bindings, you can use these events with a `HostListener` as well:
509+
510+
```HTML
511+
<!-- pan events -->
512+
<div (pan)="logEvent($event)"></div>
513+
<div (panstart)="logEvent($event)"></div>
514+
<div (panmove)="logEvent($event)"></div>
515+
<div (panend)="logEvent($event)"></div>
516+
<div (pancancel)="logEvent($event)"></div>
517+
<div (panleft)="logEvent($event)"></div>
518+
<div (panright)="logEvent($event)"></div>
519+
<div (panup)="logEvent($event)"></div>
520+
<div (pandown)="logEvent($event)"></div>
521+
522+
<!-- pinch events -->
523+
<div (pinch)="logEvent($event)"></div>
524+
<div (pinchstart)="logEvent($event)"></div>
525+
<div (pinchmove)="logEvent($event)"></div>
526+
<div (pinchend)="logEvent($event)"></div>
527+
<div (pinchcancel)="logEvent($event)"></div>
528+
<div (pinchin)="logEvent($event)"></div>
529+
<div (pinchout)="logEvent($event)"></div>
530+
531+
<!-- press events -->
532+
<div (press)="logEvent($event)"></div>
533+
<div (pressup)="logEvent($event)"></div>
534+
535+
<!-- rotate events -->
536+
<div (rotate)="logEvent($event)"></div>
537+
<div (rotatestart)="logEvent($event)"></div>
538+
<div (rotatemove)="logEvent($event)"></div>
539+
<div (rotateend)="logEvent($event)"></div>
540+
<div (rotatecancel)="logEvent($event)"></div>
541+
542+
<!-- swipe events -->
543+
<div (swipe)="logEvent($event)"></div>
544+
<div (swipeleft)="logEvent($event)"></div>
545+
<div (swiperight)="logEvent($event)"></div>
546+
<div (swipeup)="logEvent($event)"></div>
547+
<div (swipedown)="logEvent($event)"></div>
548+
549+
<!-- tap event -->
550+
<div (tap)="logEvent($event)"></div>
551+
```
552+
</details>
553+
554+
#### Links
555+
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
556+
557+
<br>[⭐ 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)
558+
<br><br>
477559
### Loader Component
478560
You can create own helper component and use it instead of `*ngIf`.
479561

@@ -593,6 +675,30 @@ https://angular.io/guide/styleguide#style-05-13
593675

594676
<br>[⭐ 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)
595677
<br><br>
678+
### Safe Navigation Operator
679+
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.
680+
681+
```html
682+
<p> I will work even if student is null or undefined: {{student?.name}} </p>
683+
```
684+
685+
<details>
686+
<summary>Bonus</summary>
687+
688+
```html
689+
{{a?.b?.c}}
690+
```
691+
Underneath will be compiled to.
692+
```html
693+
(_co.a == null)? null: ((_co.a.b == null)? null: _co.a.b.c));
694+
```
695+
</details>
696+
697+
#### Links
698+
https://github.com/angular/angular/issues/791
699+
700+
<br>[⭐ 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)
701+
<br><br>
596702
### trackBy in for loops
597703
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.
598704

builder/build.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const config = require('./config');
55
const screenshots = require('./plugins/screenshots');
66

77
const server = serve({
8-
port: 8082,
8+
port: 8083,
99
verbose: true
1010
});
1111

builder/helpers/index.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const slugify = require('slugify');
22
const groupBy = require('handlebars-group-by');
3-
const {inspect} = require('util');
43

54
let group;
65

@@ -32,7 +31,6 @@ function highlight(code, lang) {
3231
*/
3332
function stripTypeScript(code){
3433
return code.slice(13, -3).trim();
35-
3634
}
3735

3836
module.exports = {
@@ -57,6 +55,9 @@ module.exports = {
5755
}));
5856
return JSON.stringify(newSnippet, null, 2)
5957
},
58+
hasCode(code){
59+
return code.componentcode || code.modulecode;
60+
},
6061
codeToBase64(code) {
6162
const files = {};
6263
if(code.componentcode){
@@ -88,8 +89,3 @@ module.exports = {
8889
].map(path => snippetsByPath[path]);
8990
}
9091
};
91-
92-
93-
// eyJjb21wb25lbnRjb2RlIjoiYGBgdHlwZXNjcmlwdFxuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuIHNlbGVjdG9yOiAnbXktYXBwJyxcbiB0ZW1wbGF0ZTogYFxuIDxoMj5UeXBlIHNvbWV0aGluZyBpbiB0aGUgaW5wdXQgYW5kIGhpdCBjb250cm9sK2VudGVyIHRvIFxuIHVwZGF0ZSB0aGUgdmFsdWUgYmVsb3c6PC9oMj5cblxuIDxoMT57e3ZhbHVlIHx8ICdubyB2YWx1ZSd9fTwvaDE+XG4gPGlucHV0IChrZXlkb3duLmNvbnRyb2wuZW50ZXIpPVwidmFsdWU9JGV2ZW50LnRhcmdldC52YWx1ZTsgJGV2ZW50LnRhcmdldC52YWx1ZSA9ICcnXCI+XG4gYFxufSlcbmV4cG9ydCBjbGFzcyBBcHBDb21wb25lbnQge1xuIHZhbHVlOiBzdHJpbmc7XG59XG5gYGAifQ==
94-
// eyJjb21wb25lbnRjb2RlIjoiYGBgdHlwZXNjcmlwdFxuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ215LWFwcCcsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGgyPlR5cGUgc29tZXRoaW5nIGluIHRoZSBpbnB1dCBhbmQgaGl0IGNvbnRyb2wrZW50ZXIgdG8gXG4gICAgICAgIHVwZGF0ZSB0aGUgdmFsdWUgYmVsb3c6PC9oMj5cblxuICAgIDxoMT57e3ZhbHVlIHx8ICdubyB2YWx1ZSd9fTwvaDE
95-
// eyJjb21wb25lbnRjb2RlIjoiYGBgdHlwZXNjcmlwdFxuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ215LWFwcCcsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGgyPlR5cGUgc29tZXRoaW5nIGluIHRoZSBpbnB1dCBhbmQgaGl0IGNvbnRyb2wrZW50ZXIgdG8gXG4gICAgICAgIHVwZGF0ZSB0aGUgdmFsdWUgYmVsb3c6PC9oMj5cblxuICAgIDxoMT57e3ZhbHVlIHx8ICdubyB2YWx1ZSd9fTwvaDE

builder/layouts/random.hbs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
const values = [
3+
{{#each snippets}}
4+
'{{path}}',
5+
{{/each}}
6+
];
7+
8+
const path = values[Math.floor(Math.random() * values.length)];
9+
console.log(path);
10+
window.location = '/' + path.replace('.md', '/');
11+
</script>

builder/layouts/screenshot.hbs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
{{#> head }}
2-
<title>{{ title }}</title>
3-
<style>
2+
<title>{{ title }}</title>
3+
<style>
44
.mdl-card__menu img {
5-
height: 86px;
6-
margin-top: -20px;
7-
margin-right: -30px;
5+
height: 86px;
6+
margin-top: -20px;
7+
margin-right: -30px;
88
}
9-
</style>
9+
.mdl-card__supporting-text {
10+
color: #4c4c4c;
11+
}
12+
13+
.mdl-card__title-text {
14+
font-weight: 400;
15+
}
16+
</style>
1017
{{/head }}
1118

1219
{{#> body }}
13-
<div class="mdl-card mdl-shadow--2dp card snippet-card">
14-
<div class="mdl-card__title">
15-
<h2 class="mdl-card__title-text">✅ {{title}} </h2>
16-
</div>
17-
<div class="mdl-card__supporting-text">
18-
{{{markdown content}}}
19-
</div>
20-
<div class="mdl-card__menu">
21-
<img src="public/img/logo.png" style="" alt="">
20+
<div class="mdl-card mdl-shadow--2dp card snippet-card">
21+
<div class="mdl-card__title">
22+
<h2 class="mdl-card__title-text">✅ {{title}} </h2>
23+
</div>
24+
<div class="mdl-card__supporting-text">
25+
{{{markdown content}}}
26+
</div>
27+
<div class="mdl-card__menu">
28+
<img src="public/img/logo.png" style="" alt="">
29+
</div>
2230
</div>
23-
</div>
2431
{{/body}}

builder/layouts/snippet.hbs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
11
{{#> head }}
2-
<title>{{ title }}</title>
3-
<style>
4-
.demo-card iframe {
5-
width: 100%;
6-
min-height: 50vh;
7-
}
2+
<title>{{ title }}</title>
3+
<style>
4+
.demo-card iframe {
5+
width: 100%;
6+
min-height: 50vh;
7+
}
88
9-
.demo-card {
10-
height: 100%;
11-
}
12-
</style>
13-
<meta name="twitter:card" content="summary_large_image" />
14-
<meta name="twitter:site" content="@30sec_angular">
15-
<meta name="twitter:title" content="✨ 30 Seconds of Angular: {{title}}">
16-
<meta name="twitter:text:title" content="✨ 30 Seconds of Angular ✨">
17-
<meta name="twitter:description" content="{{title}}">
18-
<meta name="twitter:image" content="{{site.base}}{{slugify title}}/preview.png">
19-
<meta name="twitter:image:alt" content="30 seconds of angular">
9+
.demo-card {
10+
height: 100%;
11+
}
12+
</style>
13+
<meta name="twitter:card" content="summary_large_image" />
14+
<meta name="twitter:site" content="@30sec_angular">
15+
<meta name="twitter:title" content="✨ 30 Seconds of Angular: {{title}}">
16+
<meta name="twitter:text:title" content="✨ 30 Seconds of Angular ✨">
17+
<meta name="twitter:description" content="{{title}}">
18+
<meta name="twitter:image" content="{{site.base}}{{slugify title}}/preview.png">
19+
<meta name="twitter:image:alt" content="30 seconds of angular">
2020
{{/head }}
2121

2222
{{#> full-body }}
2323

24-
{{>snippet}}
24+
{{>snippet}}
2525

26-
<div class="mdl-card mdl-shadow--2dp card demo-card">
27-
<iframe src="https://codelab.fun/angular/playground?code={{codeToBase64 this}}"></iframe>
28-
</div>
26+
{{#if (hasCode this)}}
27+
<div class="mdl-card mdl-shadow--2dp card demo-card">
28+
<iframe src="https://codelab.fun/angular/playground?code={{codeToBase64 this}}"></iframe>
29+
</div>
30+
{{/if}}
2931

3032
{{/full-body}}
31-

builder/plugins/screenshots.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module.exports = (server) => async (files, metalsmith, done) => {
2727
.filter(file => files[file].layout === 'screenshot.hbs');
2828

2929
for (let file of names) {
30-
await page.goto(`http://localhost:8082/${file}`);
30+
await page.goto(`http://localhost:8083/${file}`);
3131
await screenshotDOMElement('.snippet-card', 'static/' + file.replace('screenshot.html', 'preview.png'), 0)
3232
}
3333

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"main": "index.js",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1",
8-
"generate": "node builder/build",
8+
"generate": "echo 'I am deprecated, use `npm run build` insted' && node builder/build",
9+
"build": "node builder/build",
910
"start": "node builder/serve",
1011
"deploy": "npm run generate && firebase deploy --only hosting:angular-30-seconds"
1112
},

snippets/angular-cheat-sheet.md

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
title: Cheat Sheets and Checklists
3+
author: kirjs
4+
twitter: kirjs
5+
level: beginner
6+
tags:
7+
- tip
8+
- cheat sheet
9+
10+
links:
11+
- https://malcoded.com/angular-cheat-sheet/
12+
- https://angular.io/guide/cheatsheet
13+
- https://angular.io/guide/styleguide
14+
---
15+
16+
# Content
17+
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.
18+
19+
Also [Angular Checklist](https://angular-checklist.io) contains is curated list of common mistakes made when developing Angular applications.

0 commit comments

Comments
 (0)