├── examples ├── src │ ├── assets │ │ └── .gitkeep │ ├── app │ │ ├── app.component.css │ │ ├── common │ │ │ ├── simple.ts │ │ │ ├── simple.model.ts │ │ │ ├── simple.enum.ts │ │ │ └── simple.interface.ts │ │ ├── components │ │ │ ├── project-folder-sturcture │ │ │ │ ├── user-story │ │ │ │ │ └── .gitkeep │ │ │ │ └── user-info │ │ │ │ │ ├── _pipes │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _constants │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _directives │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _guards │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _models │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _resolvers │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _store │ │ │ │ │ ├── actions │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── models │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ └── states │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── user-software │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── _components │ │ │ │ │ ├── _smart │ │ │ │ │ │ └── user-info │ │ │ │ │ │ │ ├── user-info.component.html │ │ │ │ │ │ │ ├── user-info.component.css │ │ │ │ │ │ │ ├── user-info.component.ts │ │ │ │ │ │ │ └── user-info.component.spec.ts │ │ │ │ │ └── _dumb │ │ │ │ │ │ └── user-info-details │ │ │ │ │ │ ├── user-info-details.component.html │ │ │ │ │ │ ├── user-info-details.component.css │ │ │ │ │ │ ├── user-info-details.component.ts │ │ │ │ │ │ └── user-info-details.component.spec.ts │ │ │ │ │ ├── _services │ │ │ │ │ ├── facade │ │ │ │ │ │ ├── user.facade.ts │ │ │ │ │ │ └── user-ngxs.facade.ts │ │ │ │ │ └── api │ │ │ │ │ │ ├── user-http.service.ts │ │ │ │ │ │ ├── user-http-mock.service.ts │ │ │ │ │ │ └── user-http-prod.service.ts │ │ │ │ │ ├── _providers │ │ │ │ │ ├── user-info.provider.ts │ │ │ │ │ └── uesr-http.provider.ts │ │ │ │ │ └── user-info.module.ts │ │ │ ├── show-mock-usage │ │ │ │ ├── show-mock-usage.component.css │ │ │ │ ├── show-mock-usage.component.html │ │ │ │ ├── show-mock-usage.component.ts │ │ │ │ └── show-mock-usage.component.spec.ts │ │ │ ├── tslint-wrong-takeuntil-rule │ │ │ │ ├── tslint-wrong-takeuntil-rule.component.css │ │ │ │ ├── tslint-wrong-takeuntil-rule.component.html │ │ │ │ ├── tslint-wrong-takeuntil-rule.component.spec.ts │ │ │ │ └── tslint-wrong-takeuntil-rule.component.ts │ │ │ ├── how-to-unsubscribe │ │ │ │ ├── unsubscribe.component.html │ │ │ │ ├── unsubscribe.component.css │ │ │ │ ├── unsubscribe.component.spec.ts │ │ │ │ └── unsubscribe.component.ts │ │ │ ├── display-block-by-default │ │ │ │ ├── display-block-by-default.html │ │ │ │ ├── display-block-by-default.css │ │ │ │ └── display-block-by-default.ts │ │ │ ├── smart-dumb-concept │ │ │ │ ├── _smart │ │ │ │ │ ├── smart.component.css │ │ │ │ │ ├── smart.component.html │ │ │ │ │ └── smart.component.ts │ │ │ │ └── _dumb │ │ │ │ │ ├── dumb-five │ │ │ │ │ ├── dumb-five.component.css │ │ │ │ │ ├── dumb-five.component.html │ │ │ │ │ ├── dumb-five.component.ts │ │ │ │ │ └── dumb-five.component.spec.ts │ │ │ │ │ ├── dumb-four │ │ │ │ │ ├── dumb-four.component.css │ │ │ │ │ ├── dumb-four.component.html │ │ │ │ │ ├── dumb-four.component.ts │ │ │ │ │ └── dumb-four.component.spec.ts │ │ │ │ │ ├── dumb-one │ │ │ │ │ ├── dumb-one.component.css │ │ │ │ │ ├── dumb-one.component.html │ │ │ │ │ ├── dumb-one.component.ts │ │ │ │ │ └── dumb-one.component.spec.ts │ │ │ │ │ ├── dumb-three │ │ │ │ │ ├── dumb-three.component.css │ │ │ │ │ ├── dumb-three.component.html │ │ │ │ │ ├── dumb-three.component.ts │ │ │ │ │ └── dumb-three.component.spec.ts │ │ │ │ │ └── dumb-two │ │ │ │ │ ├── dumb-two.component.css │ │ │ │ │ ├── dumb-two.component.html │ │ │ │ │ ├── dumb-two.component.ts │ │ │ │ │ └── dumb-two.component.spec.ts │ │ │ ├── http-proxy-example │ │ │ │ ├── http-proxy-example.component.html │ │ │ │ ├── http-proxy-example.component.css │ │ │ │ ├── http.service.ts │ │ │ │ ├── http-proxy.module.ts │ │ │ │ ├── http-proxy-example.component.ts │ │ │ │ └── http-proxy-example.component.spec.ts │ │ │ ├── change-detection-by-default │ │ │ │ ├── change-detection-by-default.component.css │ │ │ │ ├── change-detection-by-default.component.html │ │ │ │ └── change-detection-by-default.component.ts │ │ │ ├── input-changes-detection │ │ │ │ ├── property-change │ │ │ │ │ ├── property-change.component.css │ │ │ │ │ ├── property-change.component.html │ │ │ │ │ └── property-change.component.ts │ │ │ │ └── property-changes-detection │ │ │ │ │ ├── property-changes-detection.component.css │ │ │ │ │ ├── property-changes-detection.component.html │ │ │ │ │ └── property-changes-detection.component.ts │ │ │ └── track-by-example │ │ │ │ ├── track-by-example.component.css │ │ │ │ ├── track-by-example.component.html │ │ │ │ ├── track-by-example.component.spec.ts │ │ │ │ └── track-by-example.component.ts │ │ ├── app.component.html │ │ ├── data-facade │ │ │ ├── _models │ │ │ │ ├── routes.ts │ │ │ │ ├── animals.ts │ │ │ │ ├── data-with-status.ts │ │ │ │ └── status-data.ts │ │ │ ├── _components │ │ │ │ └── _smart │ │ │ │ │ ├── animal │ │ │ │ │ ├── animal.component.css │ │ │ │ │ ├── animal.component.html │ │ │ │ │ ├── animal.component.spec.ts │ │ │ │ │ └── animal.component.ts │ │ │ │ │ └── no-facade │ │ │ │ │ ├── no-facade.component.css │ │ │ │ │ ├── no-facade.component.html │ │ │ │ │ ├── no-facade.component.spec.ts │ │ │ │ │ └── no-facade.component.ts │ │ │ ├── _store │ │ │ │ ├── models │ │ │ │ │ └── animal-state.ts │ │ │ │ └── states │ │ │ │ │ ├── animal.actions.ts │ │ │ │ │ └── animal-state.ts │ │ │ ├── _services │ │ │ │ ├── api │ │ │ │ │ ├── animal-http.service.ts │ │ │ │ │ └── animal-http-production.service.ts │ │ │ │ └── facade │ │ │ │ │ ├── animal.facade.ts │ │ │ │ │ └── animal-ngxs.facade.ts │ │ │ ├── _providers │ │ │ │ ├── animal-facde.provider.ts │ │ │ │ └── animal-http.provider.ts │ │ │ └── data-facade.module.ts │ │ ├── dialog-as-service │ │ │ ├── _components │ │ │ │ ├── _smart │ │ │ │ │ └── dialog-show-room │ │ │ │ │ │ ├── dialog-show-room.component.html │ │ │ │ │ │ ├── dialog-show-room.component.css │ │ │ │ │ │ ├── dialog-show-room.component.spec.ts │ │ │ │ │ │ └── dialog-show-room.component.ts │ │ │ │ └── _dumb │ │ │ │ │ └── info │ │ │ │ │ ├── info.component.html │ │ │ │ │ ├── info.component.css │ │ │ │ │ ├── info.component.spec.ts │ │ │ │ │ └── info.component.ts │ │ │ ├── _models │ │ │ │ ├── base-dialog-data.ts │ │ │ │ └── one-button-dialog.model.ts │ │ │ ├── _providers │ │ │ │ └── dialog-as-service.provider.ts │ │ │ ├── dialog-service.module.ts │ │ │ └── _service │ │ │ │ └── dialog.service.ts │ │ ├── service │ │ │ ├── logger.service.ts │ │ │ ├── my-logger.service.ts │ │ │ ├── my-logger-mock.service.ts │ │ │ └── unsubscribe.service.ts │ │ ├── app.component.ts │ │ ├── providers │ │ │ └── logger-service.provider.ts │ │ ├── app.component.spec.ts │ │ └── app.module.ts │ ├── favicon.ico │ ├── environments │ │ ├── models │ │ │ └── environment.ts │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── styles.css │ ├── main.ts │ ├── index.html │ ├── test.ts │ └── polyfills.ts ├── .prettierignore ├── dist │ └── angular-best-practicies │ │ ├── styles.3ff695c00d717f2d2a11.css │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── runtime.7b63b9fd40098a2e8207.js │ │ ├── 3rdpartylicenses.txt │ │ └── polyfills.94daefd414b8355106ab.js ├── proxy.conf.json ├── .idea │ ├── .gitignore │ ├── codeStyles │ │ ├── codeStyleConfig.xml │ │ └── Project.xml │ ├── vcs.xml │ ├── prettier.xml │ ├── inspectionProfiles │ │ └── Project_Default.xml │ ├── modules.xml │ └── angular-best-practicies.iml ├── .prettierrc.json ├── e2e │ ├── src │ │ ├── app.po.ts │ │ └── app.e2e-spec.ts │ ├── tsconfig.json │ └── protractor.conf.js ├── .editorconfig ├── tsconfig.app.json ├── tsconfig.spec.json ├── .browserslistrc ├── tsconfig.json ├── karma.conf.js ├── package.json ├── tslint.json └── angular.json ├── .gitattributes ├── .gitignore └── LICENSE /examples/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /examples/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/.prettierignore: -------------------------------------------------------------------------------- 1 | src/assets 2 | -------------------------------------------------------------------------------- /examples/src/app/common/simple.ts: -------------------------------------------------------------------------------- 1 | export class Simple {} 2 | -------------------------------------------------------------------------------- /examples/dist/angular-best-practicies/styles.3ff695c00d717f2d2a11.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/common/simple.model.ts: -------------------------------------------------------------------------------- 1 | export class SimpleModel {} 2 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-story/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/show-mock-usage/show-mock-usage.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_pipes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_constants/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_directives/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_guards/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_resolvers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_store/actions/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_store/models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_store/states/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/user-software/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/src/app/components/tslint-wrong-takeuntil-rule/tslint-wrong-takeuntil-rule.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/src/app/components/how-to-unsubscribe/unsubscribe.component.html: -------------------------------------------------------------------------------- 1 |

unsubscribe works!

2 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_models/routes.ts: -------------------------------------------------------------------------------- 1 | export enum Routes { 2 | ANIMAL = 'animal', 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/common/simple.enum.ts: -------------------------------------------------------------------------------- 1 | export enum SimpleEnum { 2 | SimpleEnum = 'SimpleEnum', 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/display-block-by-default/display-block-by-default.html: -------------------------------------------------------------------------------- 1 |

test works!

2 | -------------------------------------------------------------------------------- /examples/src/app/components/show-mock-usage/show-mock-usage.component.html: -------------------------------------------------------------------------------- 1 |

show-mock-usage works!

2 | -------------------------------------------------------------------------------- /examples/src/app/common/simple.interface.ts: -------------------------------------------------------------------------------- 1 | export interface ISimpleInterface { 2 | todo(): void; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/how-to-unsubscribe/unsubscribe.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_smart/smart.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_models/animals.ts: -------------------------------------------------------------------------------- 1 | export interface Animals { 2 | animals: string[]; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/http-proxy-example/http-proxy-example.component.html: -------------------------------------------------------------------------------- 1 |

http-proxy-example works!

2 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/animal/animal.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/display-block-by-default/display-block-by-default.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/http-proxy-example/http-proxy-example.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/no-facade/no-facade.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evoytenkoapps/angular-best-practices/HEAD/examples/src/favicon.ico -------------------------------------------------------------------------------- /examples/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/data": { 3 | "target": "http://localhost:8082", 4 | "secure": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-five/dumb-five.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-four/dumb-four.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-one/dumb-one.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-three/dumb-three.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-two/dumb-two.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/animal/animal.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/src/app/components/change-detection-by-default/change-detection-by-default.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/input-changes-detection/property-change/property-change.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_smart/dialog-show-room/dialog-show-room.component.html: -------------------------------------------------------------------------------- 1 |

dialog-show-room works!

2 | -------------------------------------------------------------------------------- /examples/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /examples/src/app/components/track-by-example/track-by-example.component.css: -------------------------------------------------------------------------------- 1 | .table { 2 | display: flex; 3 | flex-direction: row; 4 | } 5 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_smart/dialog-show-room/dialog-show-room.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/change-detection-by-default/change-detection-by-default.component.html: -------------------------------------------------------------------------------- 1 |

change-detection-by-default works!

2 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_smart/user-info/user-info.component.html: -------------------------------------------------------------------------------- 1 |

user-info works!

2 | -------------------------------------------------------------------------------- /examples/src/app/components/tslint-wrong-takeuntil-rule/tslint-wrong-takeuntil-rule.component.html: -------------------------------------------------------------------------------- 1 |

tslint-wrong-takeuntil-rule works!

2 | -------------------------------------------------------------------------------- /examples/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "singleQuote": true, 4 | "useTabs": false, 5 | "tabWidth": 2, 6 | "semi": true 7 | } 8 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_store/models/animal-state.ts: -------------------------------------------------------------------------------- 1 | export interface AnimalStateModel { 2 | animals: string[]; 3 | counter: number; 4 | } 5 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_smart/user-info/user-info.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/input-changes-detection/property-changes-detection/property-changes-detection.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/app/components/input-changes-detection/property-changes-detection/property-changes-detection.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_dumb/user-info-details/user-info-details.component.html: -------------------------------------------------------------------------------- 1 |

user-info-details works!

2 | -------------------------------------------------------------------------------- /examples/dist/angular-best-practicies/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evoytenkoapps/angular-best-practices/HEAD/examples/dist/angular-best-practicies/favicon.ico -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_dumb/user-info-details/user-info-details.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /examples/src/environments/models/environment.ts: -------------------------------------------------------------------------------- 1 | export interface Environment { 2 | production: boolean; 3 | isUseLogger: boolean; 4 | iseUseApi: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_smart/smart.component.html: -------------------------------------------------------------------------------- 1 |

Smart component

2 | 3 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_models/data-with-status.ts: -------------------------------------------------------------------------------- 1 | import { StatusData } from './status-data'; 2 | 3 | export interface DataWithStatus { 4 | data: T; 5 | status: StatusData; 6 | } 7 | -------------------------------------------------------------------------------- /examples/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-five/dumb-five.component.html: -------------------------------------------------------------------------------- 1 |

dumb-five works!

2 |
{{ dataFive }}
3 | 4 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-one/dumb-one.component.html: -------------------------------------------------------------------------------- 1 |

dumb-one works!

2 | 3 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-four/dumb-four.component.html: -------------------------------------------------------------------------------- 1 |

dumb-four works!

2 | 3 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-two/dumb-two.component.html: -------------------------------------------------------------------------------- 1 |

dumb-two works!

2 | 3 | -------------------------------------------------------------------------------- /examples/src/app/service/logger.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable() 4 | export abstract class LoggerService { 5 | public abstract log(...args: any): void; 6 | } 7 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-three/dumb-three.component.html: -------------------------------------------------------------------------------- 1 |

dumb-three works!

2 | 3 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_models/status-data.ts: -------------------------------------------------------------------------------- 1 | export enum StatusData { 2 | PENDING = 'PENDING', 3 | LOADING = 'LOADING', 4 | LOADED = 'LOADED', 5 | ERROR = 'ERROR', 6 | CANCEL = 'CANCEL', 7 | } 8 | -------------------------------------------------------------------------------- /examples/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_models/base-dialog-data.ts: -------------------------------------------------------------------------------- 1 | export interface BaseDialogData { 2 | readonly label: string; 3 | readonly content?: string; 4 | readonly isDisableCloseOnBackClick?: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /examples/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /examples/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | import { Environment } from './models/environment'; 2 | 3 | export const environment: Environment = { 4 | iseUseApi: true, 5 | production: true, 6 | isUseLogger: false, 7 | }; 8 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_services/facade/user.facade.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | export abstract class UserFacade { 4 | public abstract getUser(): Observable; 5 | } 6 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_models/one-button-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { BaseDialogData } from './base-dialog-data'; 2 | 3 | export interface VmOneButtonDialogModel extends BaseDialogData { 4 | readonly btnText: string; 5 | } 6 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_services/api/user-http.service.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | export abstract class UserHttpService { 4 | public abstract getUer(): Observable; 5 | } 6 | -------------------------------------------------------------------------------- /examples/src/app/components/input-changes-detection/property-change/property-change.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /examples/.idea/prettier.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_providers/dialog-as-service.provider.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from '@angular/core'; 2 | import { DialogService } from '../_service/dialog.service'; 3 | 4 | // export const DIALOG_AS_SERVICE_PROVIDER: Provider = { 5 | // provide: DialogService, 6 | // }; 7 | -------------------------------------------------------------------------------- /examples/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'], 7 | }) 8 | export class AppComponent { 9 | title = 'angular-best-practicies'; 10 | } 11 | -------------------------------------------------------------------------------- /examples/src/app/service/my-logger.service.ts: -------------------------------------------------------------------------------- 1 | import { LoggerService } from './logger.service'; 2 | import { Injectable } from '@angular/core'; 3 | 4 | @Injectable() 5 | export class MyLoggerService extends LoggerService { 6 | log(): void { 7 | console.log('MyLoggerService'); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_store/states/animal.actions.ts: -------------------------------------------------------------------------------- 1 | export class AddAnimal { 2 | static readonly type = '[Zoo] Add Animal'; 3 | constructor(public animal: string) {} 4 | } 5 | 6 | export class ResetAnimals { 7 | static readonly type = '[Zoo] Reset Animal'; 8 | constructor() {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /examples/src/app/service/my-logger-mock.service.ts: -------------------------------------------------------------------------------- 1 | import { LoggerService } from './logger.service'; 2 | import { Injectable } from '@angular/core'; 3 | 4 | @Injectable() 5 | export class MyLoggerMockService extends LoggerService { 6 | log(): void { 7 | console.log('MyLoggerMockService'); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_services/api/user-http-mock.service.ts: -------------------------------------------------------------------------------- 1 | import { UserHttpService } from './user-http.service'; 2 | import { Observable, of } from 'rxjs'; 3 | 4 | export class UserHttpMockService extends UserHttpService { 5 | getUer(): Observable { 6 | return of(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | async navigateTo(): Promise { 5 | return browser.get(browser.baseUrl); 6 | } 7 | 8 | async getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_services/api/animal-http.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Observable } from 'rxjs'; 3 | import { DataWithStatus } from '../../_models/data-with-status'; 4 | 5 | @Injectable() 6 | export abstract class AnimalHttpService { 7 | abstract getAnimals(): Observable>; 8 | } 9 | -------------------------------------------------------------------------------- /examples/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../out-tsc/e2e", 6 | "module": "commonjs", 7 | "target": "es2018", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_providers/animal-facde.provider.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from '@angular/core'; 2 | import { AnimalFacade } from '../_services/facade/animal.facade'; 3 | import { AnimalNgxsFacade } from '../_services/facade/animal-ngxs.facade'; 4 | 5 | export const ANIMAL_FACADE_PROVIDER: Provider = { 6 | provide: AnimalFacade, 7 | useClass: AnimalNgxsFacade, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_providers/user-info.provider.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from '@angular/core'; 2 | import { UserFacade } from '../_services/facade/user.facade'; 3 | import { UserNgxsFacade } from '../_services/facade/user-ngxs.facade'; 4 | 5 | export const USER_FACADE_PROVIDER: Provider = { 6 | provide: UserFacade, 7 | useClass: UserNgxsFacade, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/no-facade/no-facade.component.html: -------------------------------------------------------------------------------- 1 | 2 |

Loading

3 |

Error

4 | 5 | 6 | 7 |
8 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_providers/animal-http.provider.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from '@angular/core'; 2 | import { AnimalHttpService } from '../_services/api/animal-http.service'; 3 | import { AnimalHttpProductionService } from '../_services/api/animal-http-production.service'; 4 | 5 | export const ANIMAL_HTTP_PROVIDER: Provider = { 6 | provide: AnimalHttpService, 7 | useClass: AnimalHttpProductionService, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/src/app/components/http-proxy-example/http.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { Observable } from 'rxjs'; 4 | 5 | @Injectable() 6 | export class HttpService { 7 | constructor(private httpClient: HttpClient) {} 8 | 9 | public getData(): Observable { 10 | return this.httpClient.get('/data'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_services/facade/user-ngxs.facade.ts: -------------------------------------------------------------------------------- 1 | import { UserFacade } from './user.facade'; 2 | import { Observable, of } from 'rxjs'; 3 | import { Store } from '@ngxs/store'; 4 | 5 | export class UserNgxsFacade extends UserFacade { 6 | constructor(private readonly store: Store) { 7 | super(); 8 | } 9 | 10 | getUser(): Observable { 11 | return of(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /examples/src/app/components/track-by-example/track-by-example.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{ item.digit }} 5 |
6 | 7 |
8 | 9 |
10 |
{{ item.digit }}
11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_dumb/info/info.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

{{ infoDialogModel.label }}

4 |

5 |
6 | 7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_services/api/user-http-prod.service.ts: -------------------------------------------------------------------------------- 1 | import { UserHttpService } from './user-http.service'; 2 | import { Observable, of } from 'rxjs'; 3 | import { HttpClient } from '@angular/common/http'; 4 | 5 | export class UserHttpProdService extends UserHttpService { 6 | constructor(private readonly http: HttpClient) { 7 | super(); 8 | } 9 | getUer(): Observable { 10 | return of(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/user-info.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { USER_HTTP_SERVICE_PROVIDER } from './_providers/uesr-http.provider'; 4 | import { USER_FACADE_PROVIDER } from './_providers/user-info.provider'; 5 | 6 | @NgModule({ 7 | declarations: [], 8 | imports: [CommonModule], 9 | providers: [USER_HTTP_SERVICE_PROVIDER, USER_FACADE_PROVIDER], 10 | }) 11 | export class UserInfoModule {} 12 | -------------------------------------------------------------------------------- /examples/src/app/components/http-proxy-example/http-proxy.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { HttpProxyExampleComponent } from './http-proxy-example.component'; 4 | import { HttpService } from './http.service'; 5 | 6 | @NgModule({ 7 | declarations: [HttpProxyExampleComponent], 8 | imports: [CommonModule], 9 | providers: [HttpService], 10 | exports: [ 11 | HttpProxyExampleComponent 12 | ] 13 | }) 14 | export class HttpProxyModule {} 15 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_smart/user-info/user-info.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-user-info', 5 | templateUrl: './user-info.component.html', 6 | styleUrls: ['./user-info.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class UserInfoComponent implements OnInit { 10 | 11 | constructor() { } 12 | 13 | ngOnInit(): void { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /examples/src/app/service/unsubscribe.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, OnDestroy } from '@angular/core'; 2 | import { Observable, Subject } from 'rxjs'; 3 | 4 | @Injectable() 5 | export class UnsubscribeService extends Observable implements OnDestroy { 6 | private readonly unsubscribe$ = new Subject(); 7 | 8 | constructor() { 9 | super((subscriber) => this.unsubscribe$.subscribe(subscriber)); 10 | } 11 | 12 | ngOnDestroy() { 13 | this.unsubscribe$.next(); 14 | this.unsubscribe$.complete(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/src/app/components/display-block-by-default/display-block-by-default.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-test', 5 | templateUrl: './display-block-by-default.html', 6 | styleUrls: ['./display-block-by-default.css'], 7 | }) 8 | // Пример работы 9 | // "@schematics/angular:component": { 10 | // "displayBlock": true 11 | // } 12 | export class DisplayBlockByDefaultComponent implements OnInit { 13 | constructor() {} 14 | 15 | ngOnInit(): void {} 16 | } 17 | -------------------------------------------------------------------------------- /examples/src/app/providers/logger-service.provider.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from '@angular/core'; 2 | import { LoggerService } from '../service/logger.service'; 3 | import { environment } from '../../environments/environment'; 4 | import { MyLoggerMockService } from '../service/my-logger-mock.service'; 5 | import { MyLoggerService } from '../service/my-logger.service'; 6 | 7 | export const LoggerServiceProvider: Provider = { 8 | provide: LoggerService, 9 | useValue: environment.isUseLogger ? new MyLoggerMockService() : new MyLoggerService(), 10 | }; 11 | -------------------------------------------------------------------------------- /examples/src/app/components/input-changes-detection/property-change/property-change.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-property-change', 5 | templateUrl: './property-change.component.html', 6 | styleUrls: ['./property-change.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class PropertyChangeComponent implements OnInit { 10 | public userName: string | null = null; 11 | constructor() {} 12 | 13 | ngOnInit(): void {} 14 | } 15 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_dumb/info/info.component.css: -------------------------------------------------------------------------------- 1 | .main { 2 | width: 554px; 3 | height: auto; 4 | padding: 24px 32px; 5 | background: #ffffff; 6 | border-radius: 16px; 7 | position: relative; 8 | } 9 | 10 | .content { 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | text-align: center; 15 | } 16 | 17 | .buttons { 18 | display: flex; 19 | flex-direction: row; 20 | } 21 | 22 | .left-button { 23 | width: 200px; 24 | margin-right: 16px; 25 | } 26 | 27 | .close { 28 | cursor: pointer; 29 | } 30 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_dumb/user-info-details/user-info-details.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-user-info-details', 5 | templateUrl: './user-info-details.component.html', 6 | styleUrls: ['./user-info-details.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class UserInfoDetailsComponent implements OnInit { 10 | 11 | constructor() { } 12 | 13 | ngOnInit(): void { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /examples/.idea/angular-best-practicies.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/src/app/components/show-mock-usage/show-mock-usage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { LoggerService } from '../../service/logger.service'; 3 | 4 | @Component({ 5 | selector: 'app-show-mock-usage', 6 | templateUrl: './show-mock-usage.component.html', 7 | styleUrls: ['./show-mock-usage.component.css'], 8 | }) 9 | export class ShowMockUsageComponent implements OnInit { 10 | // Так не делаем 11 | private a?: number; 12 | 13 | constructor(private logger: LoggerService) {} 14 | 15 | ngOnInit(): void { 16 | this.logger.log(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_providers/uesr-http.provider.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from '@angular/core'; 2 | import { UserHttpService } from '../_services/api/user-http.service'; 3 | import { environment } from '../../../../../environments/environment'; 4 | import { UserHttpProdService } from '../_services/api/user-http-prod.service'; 5 | import { UserHttpMockService } from '../_services/api/user-http-mock.service'; 6 | 7 | export const USER_HTTP_SERVICE_PROVIDER: Provider = { 8 | provide: UserHttpService, 9 | useClass: environment.iseUseApi ? UserHttpProdService : UserHttpMockService, 10 | }; 11 | -------------------------------------------------------------------------------- /examples/dist/angular-best-practicies/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularBestPracticies 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_services/facade/animal.facade.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { AnimalStateModel } from '../../_store/models/animal-state'; 3 | import { Injectable } from '@angular/core'; 4 | import { StatusData } from '../../_models/status-data'; 5 | 6 | @Injectable() 7 | export abstract class AnimalFacade { 8 | public abstract addAnimal(animal: string): void; 9 | public abstract resetAnimals(): void; 10 | public abstract getAnimals(): Observable; 11 | public abstract getAddAnimalStatus(): Observable; 12 | public abstract getAnimalStateModel(): Observable; 13 | } 14 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/dialog-service.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { DialogService } from './_service/dialog.service'; 3 | import { InfoComponent } from './_components/_dumb/info/info.component'; 4 | import { MatDialogModule } from '@angular/material/dialog'; 5 | import { DialogShowRoomComponent } from './_components/_smart/dialog-show-room/dialog-show-room.component'; 6 | 7 | @NgModule({ 8 | imports: [MatDialogModule], 9 | providers: [DialogService], 10 | exports: [DialogShowRoomComponent], 11 | declarations: [InfoComponent, DialogShowRoomComponent], 12 | }) 13 | export class DialogServiceModule {} 14 | -------------------------------------------------------------------------------- /examples/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularBestPracticies 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-two/dumb-two.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-dumb-two', 5 | templateUrl: './dumb-two.component.html', 6 | styleUrls: ['./dumb-two.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DumbTwoComponent implements OnInit { 10 | @Input() dataTwo: number | null = null; 11 | @Output() dataTwoChange: EventEmitter = new EventEmitter(); 12 | constructor() {} 13 | 14 | ngOnInit(): void {} 15 | 16 | public setData(data: number): void { 17 | this.dataTwoChange.emit(data); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-one/dumb-one.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-dumb-one', 5 | templateUrl: './dumb-one.component.html', 6 | styleUrls: ['./dumb-one.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DumbOneComponent implements OnInit { 10 | @Input() dataOne: number | null = null; 11 | @Output() dataOneChange: EventEmitter = new EventEmitter(); 12 | 13 | constructor() {} 14 | 15 | ngOnInit(): void {} 16 | 17 | public setData(data: number): void { 18 | this.dataOneChange.emit(data); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-four/dumb-four.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-dumb-four', 5 | templateUrl: './dumb-four.component.html', 6 | styleUrls: ['./dumb-four.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DumbFourComponent implements OnInit { 10 | @Input() dataFour: number | null = null; 11 | @Output() dataFourChange: EventEmitter = new EventEmitter(); 12 | constructor() {} 13 | 14 | ngOnInit(): void {} 15 | 16 | public setData(data: number): void { 17 | this.dataFourChange.emit(data); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-three/dumb-three.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-dumb-three', 5 | templateUrl: './dumb-three.component.html', 6 | styleUrls: ['./dumb-three.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DumbThreeComponent implements OnInit { 10 | @Input() dataThree: number | null = null; 11 | @Output() dataThreeChange: EventEmitter = new EventEmitter(); 12 | constructor() {} 13 | 14 | ngOnInit(): void {} 15 | 16 | public setData(data: number): void { 17 | this.dataThreeChange.emit(data); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_smart/smart.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | import { LoggerService } from '../../../service/logger.service'; 3 | 4 | @Component({ 5 | selector: 'app-smart-dumb-concept', 6 | templateUrl: './smart.component.html', 7 | styleUrls: ['./smart.component.css'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class SmartComponent implements OnInit { 11 | public smartData: number = 1; 12 | constructor(private loggerService: LoggerService) {} 13 | 14 | ngOnInit(): void {} 15 | 16 | public setData(data: number): void { 17 | this.loggerService.log('setData', data); 18 | this.smartData = data; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/src/app/components/change-detection-by-default/change-detection-by-default.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-change-detection-by-default', 5 | templateUrl: './change-detection-by-default.component.html', 6 | styleUrls: ['./change-detection-by-default.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | // Пример создания компонента со стратегией OnPush через ng g c по правилу angular.json 10 | // "@schematics/angular:component": { 11 | // "displayBlock": true, 12 | // "changeDetection": "OnPush" 13 | // } 14 | export class ChangeDetectionByDefaultComponent implements OnInit { 15 | constructor() {} 16 | 17 | ngOnInit(): void {} 18 | } 19 | -------------------------------------------------------------------------------- /examples/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-five/dumb-five.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-dumb-five', 5 | templateUrl: './dumb-five.component.html', 6 | styleUrls: ['./dumb-five.component.css'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DumbFiveComponent implements OnInit { 10 | @Input() dataFive: number | null = null; 11 | @Output() dataFiveChange: EventEmitter = new EventEmitter(); 12 | constructor() {} 13 | 14 | ngOnInit(): void {} 15 | 16 | public changeData(): void { 17 | if (this.dataFive) { 18 | this.dataFiveChange.emit(++this.dataFive); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_dumb/info/info.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { InfoComponent } from './info.component'; 4 | 5 | describe('InfoComponent', () => { 6 | let component: InfoComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ InfoComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(InfoComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, logging } from 'protractor'; 2 | import { AppPage } from './app.po'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', async () => { 12 | await page.navigateTo(); 13 | expect(await page.getTitleText()).toEqual('angular-best-practicies app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/animal/animal.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AnimalComponent } from './animal.component'; 4 | 5 | describe('AnimalComponent', () => { 6 | let component: AnimalComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AnimalComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AnimalComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-one/dumb-one.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DumbOneComponent } from './dumb-one.component'; 4 | 5 | describe('DumbOneComponent', () => { 6 | let component: DumbOneComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DumbOneComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DumbOneComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-two/dumb-two.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DumbTwoComponent } from './dumb-two.component'; 4 | 5 | describe('DumbTwoComponent', () => { 6 | let component: DumbTwoComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DumbTwoComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DumbTwoComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/no-facade/no-facade.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NoFacadeComponent } from './no-facade.component'; 4 | 5 | describe('NoFacadeComponent', () => { 6 | let component: NoFacadeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NoFacadeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NoFacadeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_service/dialog.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { BaseDialogData } from '../_models/base-dialog-data'; 3 | import { ComponentType } from '@angular/cdk/overlay'; 4 | import { Observable } from 'rxjs'; 5 | import { MatDialog, MatDialogConfig } from '@angular/material/dialog'; 6 | 7 | @Injectable() 8 | export class DialogService { 9 | constructor(private dialog: MatDialog) {} 10 | 11 | public showDialog(component: ComponentType, data?: D): Observable { 12 | const materialConfig: MatDialogConfig | undefined = data 13 | ? { disableClose: data?.isDisableCloseOnBackClick, data } 14 | : data; 15 | return this.dialog.open(component, materialConfig).afterClosed(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-five/dumb-five.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DumbFiveComponent } from './dumb-five.component'; 4 | 5 | describe('DumbFiveComponent', () => { 6 | let component: DumbFiveComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DumbFiveComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DumbFiveComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-four/dumb-four.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DumbFourComponent } from './dumb-four.component'; 4 | 5 | describe('DumbFourComponent', () => { 6 | let component: DumbFourComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DumbFourComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DumbFourComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/how-to-unsubscribe/unsubscribe.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UnsubscribeComponent } from './unsubscribe.component'; 4 | 5 | describe('UnsubscribeComponent', () => { 6 | let component: UnsubscribeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ UnsubscribeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UnsubscribeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/smart-dumb-concept/_dumb/dumb-three/dumb-three.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DumbThreeComponent } from './dumb-three.component'; 4 | 5 | describe('DumbThreeComponent', () => { 6 | let component: DumbThreeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DumbThreeComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DumbThreeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/show-mock-usage/show-mock-usage.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ShowMockUsageComponent } from './show-mock-usage.component'; 4 | 5 | describe('ShowMockUsageComponent', () => { 6 | let component: ShowMockUsageComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ShowMockUsageComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(ShowMockUsageComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_smart/user-info/user-info.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UserInfoComponent } from './user-info.component'; 4 | 5 | describe('UserInfoComponent', () => { 6 | let component: UserInfoComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ UserInfoComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UserInfoComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/app/components/http-proxy-example/http-proxy-example.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | import { HttpService } from './http.service'; 3 | import { takeUntil } from 'rxjs/operators'; 4 | import { UnsubscribeService } from '../../service/unsubscribe.service'; 5 | 6 | @Component({ 7 | selector: 'app-http-proxy-example', 8 | templateUrl: './http-proxy-example.component.html', 9 | styleUrls: ['./http-proxy-example.component.css'], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | }) 12 | export class HttpProxyExampleComponent implements OnInit { 13 | constructor(private httpService: HttpService, private unsubscribeService: UnsubscribeService) {} 14 | 15 | ngOnInit(): void { 16 | this.httpService.getData().pipe(takeUntil(this.unsubscribeService)).subscribe(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/src/app/components/track-by-example/track-by-example.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { TrackByExampleComponent } from './track-by-example.component'; 4 | 5 | describe('TrackByExampleComponent', () => { 6 | let component: TrackByExampleComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ TrackByExampleComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(TrackByExampleComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | 7 | declare const require: { 8 | context( 9 | path: string, 10 | deep?: boolean, 11 | filter?: RegExp 12 | ): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 20 | // Then we find all the tests. 21 | const context = require.context('./', true, /\.spec\.ts$/); 22 | // And load the modules. 23 | context.keys().map(context); 24 | -------------------------------------------------------------------------------- /examples/src/app/components/http-proxy-example/http-proxy-example.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HttpProxyExampleComponent } from './http-proxy-example.component'; 4 | 5 | describe('HttpProxyExampleComponent', () => { 6 | let component: HttpProxyExampleComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ HttpProxyExampleComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HttpProxyExampleComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | import { Environment } from './models/environment'; 6 | 7 | export const environment: Environment = { 8 | iseUseApi: false, 9 | production: false, 10 | isUseLogger: true, 11 | }; 12 | 13 | /* 14 | * For easier debugging in development mode, you can import the following file 15 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 16 | * 17 | * This import should be commented out in production mode because it will have a negative impact 18 | * on performance if an error is thrown. 19 | */ 20 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 21 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_smart/dialog-show-room/dialog-show-room.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DialogShowRoomComponent } from './dialog-show-room.component'; 4 | 5 | describe('DialogShowRoomComponent', () => { 6 | let component: DialogShowRoomComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DialogShowRoomComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DialogShowRoomComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /examples/dist 5 | /examples/tmp 6 | /examples/out-tsc 7 | # Only exists if Bazel was run 8 | /examples/bazel-out 9 | 10 | # dependencies 11 | /examples/node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | 48 | /node_modules 49 | -------------------------------------------------------------------------------- /examples/src/app/components/project-folder-sturcture/user-info/_components/_dumb/user-info-details/user-info-details.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UserInfoDetailsComponent } from './user-info-details.component'; 4 | 5 | describe('UserInfoDetailsComponent', () => { 6 | let component: UserInfoDetailsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ UserInfoDetailsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UserInfoDetailsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "sourceMap": true, 12 | "declaration": false, 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "target": "es2015", 18 | "module": "es2020", 19 | "lib": [ 20 | "es2018", 21 | "dom" 22 | ] 23 | }, 24 | "angularCompilerOptions": { 25 | "enableI18nLegacyMessageIdFormat": false, 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/src/app/components/tslint-wrong-takeuntil-rule/tslint-wrong-takeuntil-rule.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { TslintWrongTakeuntilRuleComponent } from './tslint-wrong-takeuntil-rule.component'; 4 | 5 | describe('TslintWrongTakeuntilRuleComponent', () => { 6 | let component: TslintWrongTakeuntilRuleComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [TslintWrongTakeuntilRuleComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(TslintWrongTakeuntilRuleComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_smart/dialog-show-room/dialog-show-room.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | import { InfoComponent } from '../../_dumb/info/info.component'; 3 | import { DialogService } from '../../../_service/dialog.service'; 4 | import { VmOneButtonDialogModel } from '../../../_models/one-button-dialog.model'; 5 | 6 | @Component({ 7 | selector: 'app-dialog-show-room', 8 | templateUrl: './dialog-show-room.component.html', 9 | styleUrls: ['./dialog-show-room.component.css'], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | }) 12 | export class DialogShowRoomComponent implements OnInit { 13 | constructor(private dialogService: DialogService) {} 14 | 15 | ngOnInit(): void { 16 | this.dialogService.showDialog(InfoComponent, { 17 | label: 'Labels', 18 | content: 'Content', 19 | btnText: 'buttonText', 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/src/app/dialog-as-service/_components/_dumb/info/info.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; 2 | import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; 3 | import { VmOneButtonDialogModel } from '../../../_models/one-button-dialog.model'; 4 | 5 | @Component({ 6 | selector: 'app-info', 7 | templateUrl: './info.component.html', 8 | styleUrls: ['./info.component.css'], 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | }) 11 | export class InfoComponent implements OnInit { 12 | public infoDialogModel: VmOneButtonDialogModel; 13 | 14 | constructor( 15 | @Inject(MAT_DIALOG_DATA) private data: VmOneButtonDialogModel, 16 | private dialogRef: MatDialogRef 17 | ) { 18 | this.infoDialogModel = data; 19 | } 20 | 21 | ngOnInit(): void {} 22 | 23 | public onBtnClick(): void { 24 | this.dialogRef.close(); 25 | } 26 | 27 | public onCloseClick(): void { 28 | this.dialogRef.close(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | SELENIUM_PROMISE_MANAGER: false, 20 | baseUrl: 'http://localhost:4200/', 21 | framework: 'jasmine', 22 | jasmineNodeOpts: { 23 | showColors: true, 24 | defaultTimeoutInterval: 30000, 25 | print: function() {} 26 | }, 27 | onPrepare() { 28 | require('ts-node').register({ 29 | project: require('path').join(__dirname, './tsconfig.json') 30 | }); 31 | jasmine.getEnv().addReporter(new SpecReporter({ 32 | spec: { 33 | displayStacktrace: StacktraceOption.PRETTY 34 | } 35 | })); 36 | } 37 | }; -------------------------------------------------------------------------------- /examples/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have as title 'angular-best-practicies'`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('angular-best-practicies'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement; 27 | expect(compiled.querySelector('.content span').textContent).toContain('angular-best-practicies app is running!'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/animal/animal.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; 2 | import { AnimalFacade } from '../../../_services/facade/animal.facade'; 3 | import { Unsubscribable } from 'rxjs'; 4 | import { UnsubscribeService } from '../../../../service/unsubscribe.service'; 5 | import { takeUntil } from 'rxjs/operators'; 6 | 7 | @Component({ 8 | selector: 'app-animal', 9 | templateUrl: './animal.component.html', 10 | styleUrls: ['./animal.component.css'], 11 | changeDetection: ChangeDetectionStrategy.OnPush, 12 | providers: [UnsubscribeService], 13 | }) 14 | export class AnimalComponent implements OnInit { 15 | public animals: string[] = []; 16 | 17 | constructor(private animalFacade: AnimalFacade, private unsubscribeService: UnsubscribeService) {} 18 | 19 | ngOnInit(): void { 20 | this.animalFacade 21 | .getAnimals() 22 | .pipe(takeUntil(this.unsubscribeService)) 23 | .subscribe((animals: string[]) => { 24 | console.log('animals', animals); 25 | this.animals = animals; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/src/app/components/tslint-wrong-takeuntil-rule/tslint-wrong-takeuntil-rule.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy, OnInit } from '@angular/core'; 2 | import { Subject } from 'rxjs'; 3 | import { takeUntil, tap } from 'rxjs/operators'; 4 | 5 | @Component({ 6 | selector: 'app-tslint-wrong-takeuntil-rule', 7 | templateUrl: './tslint-wrong-takeuntil-rule.component.html', 8 | styleUrls: ['./tslint-wrong-takeuntil-rule.component.css'], 9 | }) 10 | export class TslintWrongTakeuntilRuleComponent implements OnInit, OnDestroy { 11 | subject: Subject = new Subject(); 12 | destroyer: Subject = new Subject(); 13 | 14 | constructor() {} 15 | 16 | ngOnInit(): void { 17 | this.subject 18 | .asObservable() 19 | .pipe( 20 | // Пример кривой отписки для проверки tslint rule 21 | takeUntil(this.destroyer), 22 | tap((data) => console.log(data)) 23 | ) 24 | .subscribe((data) => console.log(data)); 25 | 26 | this.subject.next('NEXT'); 27 | } 28 | 29 | ngOnDestroy(): void { 30 | this.destroyer.next(); 31 | this.destroyer.complete(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_services/api/animal-http-production.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { AnimalHttpService } from './animal-http.service'; 3 | import { Observable, of } from 'rxjs'; 4 | import { HttpClient } from '@angular/common/http'; 5 | import { Routes } from '../../_models/routes'; 6 | import { DataWithStatus } from '../../_models/data-with-status'; 7 | import { StatusData } from '../../_models/status-data'; 8 | import { catchError, map, startWith } from 'rxjs/operators'; 9 | 10 | @Injectable() 11 | export class AnimalHttpProductionService extends AnimalHttpService { 12 | constructor(private httpClient: HttpClient) { 13 | super(); 14 | } 15 | 16 | getAnimals(): Observable> { 17 | return this.httpClient.get('/' + Routes.ANIMAL).pipe( 18 | map((data) => ({ data: data, status: StatusData.LOADED } as DataWithStatus)), 19 | startWith({ data: [], status: StatusData.LOADING } as DataWithStatus), 20 | catchError((error) => of({ data: [], status: StatusData.ERROR } as DataWithStatus)) 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/data-facade.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ANIMAL_FACADE_PROVIDER } from './_providers/animal-facde.provider'; 3 | import { AnimalState } from './_store/states/animal-state'; 4 | import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin'; 5 | import { NgxsModule } from '@ngxs/store'; 6 | import { AnimalComponent } from './_components/_smart/animal/animal.component'; 7 | import { CommonModule } from '@angular/common'; 8 | import { ANIMAL_HTTP_PROVIDER } from './_providers/animal-http.provider'; 9 | import { NoFacadeComponent } from './_components/_smart/no-facade/no-facade.component'; 10 | import { HttpClientModule } from '@angular/common/http'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | NgxsModule.forRoot([AnimalState], { developmentMode: true }), 15 | NgxsReduxDevtoolsPluginModule.forRoot(), 16 | CommonModule, 17 | HttpClientModule, 18 | ], 19 | providers: [ANIMAL_FACADE_PROVIDER, ANIMAL_HTTP_PROVIDER], 20 | declarations: [AnimalComponent, NoFacadeComponent], 21 | exports: [AnimalComponent, NoFacadeComponent], 22 | }) 23 | export class DataFacadeModule {} 24 | -------------------------------------------------------------------------------- /examples/src/app/components/how-to-unsubscribe/unsubscribe.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectionStrategy, OnDestroy } from '@angular/core'; 2 | import { interval, ReplaySubject, Subject } from 'rxjs'; 3 | import { takeUntil } from 'rxjs/operators'; 4 | import { UnsubscribeService } from '../../service/unsubscribe.service'; 5 | 6 | @Component({ 7 | selector: 'app-unsubscribe', 8 | templateUrl: './unsubscribe.component.html', 9 | styleUrls: ['./unsubscribe.component.css'], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | providers: [UnsubscribeService], 12 | }) 13 | export class UnsubscribeComponent implements OnInit, OnDestroy { 14 | private destroy$: ReplaySubject = new ReplaySubject(1); 15 | 16 | constructor(private unsubscribeService: UnsubscribeService) {} 17 | 18 | ngOnInit(): void { 19 | // First example 20 | interval(1000).pipe(takeUntil(this.destroy$)).subscribe(); 21 | 22 | // Second example 23 | interval(1000).pipe(takeUntil(this.unsubscribeService)).subscribe(); 24 | } 25 | 26 | ngOnDestroy(): void { 27 | this.destroy$.next(); 28 | this.destroy$.complete(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/src/app/components/track-by-example/track-by-example.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | interface ITrackItem { 4 | id: number; 5 | digit: number; 6 | } 7 | 8 | /** 9 | * Пример зачем нужен trackBy для ngFor 10 | */ 11 | 12 | @Component({ 13 | selector: 'app-track-by-example', 14 | templateUrl: './track-by-example.component.html', 15 | styleUrls: ['./track-by-example.component.css'], 16 | }) 17 | export class TrackByExampleComponent implements OnInit { 18 | public dataNoTrack: ITrackItem[] = []; 19 | public dataTrack: ITrackItem[] = []; 20 | 21 | constructor() {} 22 | 23 | ngOnInit(): void { 24 | for (let i = 0; i < 10; i++) { 25 | this.dataNoTrack.push({ id: i, digit: Math.random() }); 26 | this.dataTrack.push({ id: i, digit: Math.random() }); 27 | } 28 | } 29 | 30 | public onCloneNoTrack(): void { 31 | this.dataNoTrack = this.dataNoTrack.map((item) => ({ ...item })); 32 | } 33 | 34 | public onCloneTrackBy(): void { 35 | this.dataTrack = this.dataTrack.map((item) => ({ ...item })); 36 | } 37 | 38 | public trackById(index: number, item: ITrackItem): number { 39 | return item.id; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_components/_smart/no-facade/no-facade.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; 2 | import { StatusData } from '../../../_models/status-data'; 3 | import { UnsubscribeService } from '../../../../service/unsubscribe.service'; 4 | import { AnimalHttpService } from '../../../_services/api/animal-http.service'; 5 | import { Observable } from 'rxjs'; 6 | import { DataWithStatus } from '../../../_models/data-with-status'; 7 | 8 | @Component({ 9 | selector: 'app-no-facade', 10 | templateUrl: './no-facade.component.html', 11 | styleUrls: ['./no-facade.component.css'], 12 | changeDetection: ChangeDetectionStrategy.OnPush, 13 | providers: [UnsubscribeService], 14 | }) 15 | // Its just an example how to use http.service directly 16 | export class NoFacadeComponent implements OnInit { 17 | public animals$!: Observable>; 18 | public status: typeof StatusData = StatusData; 19 | 20 | // Its just an example, i offer you to do mapping from dto to model inside facade 21 | constructor(private unsubscribeService: UnsubscribeService, private animalHttpService: AnimalHttpService) {} 22 | 23 | ngOnInit(): void { 24 | this.animals$ = this.animalHttpService.getAnimals(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_store/states/animal-state.ts: -------------------------------------------------------------------------------- 1 | import { Action, Selector, State, StateContext } from '@ngxs/store'; 2 | import { Injectable } from '@angular/core'; 3 | import produce from 'immer'; 4 | import { AnimalStateModel } from '../models/animal-state'; 5 | import { AddAnimal, ResetAnimals } from './animal.actions'; 6 | 7 | @State({ 8 | name: 'animals', 9 | defaults: { 10 | animals: [], 11 | counter: 0, 12 | }, 13 | }) 14 | @Injectable() 15 | export class AnimalState { 16 | @Selector() 17 | static selectAnimals(state: AnimalStateModel): string[] { 18 | return state.animals; 19 | } 20 | 21 | @Selector() 22 | static selectCounter(state: AnimalStateModel): number { 23 | return state.counter; 24 | } 25 | 26 | @Selector() 27 | static selectState(state: AnimalStateModel): AnimalStateModel { 28 | return state; 29 | } 30 | 31 | @Action(AddAnimal) 32 | addAnimal({ getState, setState }: StateContext, { animal }: AddAnimal): void { 33 | setState( 34 | produce((draft) => { 35 | draft.animals.push(animal); 36 | }) 37 | ); 38 | } 39 | 40 | @Action(ResetAnimals) 41 | resetAnimals({ getState, setState }: StateContext): void { 42 | setState( 43 | produce((draft) => { 44 | draft.animals = []; 45 | }) 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/dist/angular-best-practicies/runtime.7b63b9fd40098a2e8207.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,l,f=r[0],i=r[1],p=r[2],c=0,s=[];c extends SimpleChange { 4 | previousValue: T; 5 | currentValue: T; 6 | firstChange: boolean; 7 | constructor(previousValue: T, currentValue: T, firstChange: boolean); 8 | isFirstChange(): boolean; 9 | } 10 | 11 | declare type CustomSimpleChanges = { 12 | [P in keyof T]: SimpleChangeGeneric; 13 | }; 14 | 15 | @Component({ 16 | selector: 'app-property-changes-detection', 17 | templateUrl: './property-changes-detection.component.html', 18 | styleUrls: ['./property-changes-detection.component.css'], 19 | changeDetection: ChangeDetectionStrategy.OnPush, 20 | }) 21 | export class PropertyChangesDetectionComponent implements OnInit, OnChanges { 22 | // Setter for @Input() decorator helps you to detect changes easy 23 | 24 | @Input() 25 | set userName(name: string | null) { 26 | console.log('name inside input was changed', name); 27 | if (name) { 28 | this.firstName = name; 29 | } 30 | } 31 | 32 | public firstName: string = ''; 33 | 34 | constructor() {} 35 | 36 | ngOnInit(): void {} 37 | 38 | // To avoid glitch effect you have to use OnChanges 39 | // For typesafe usage of OnChanges you may wrap SimpleChanges interface to custom generic, see above. 40 | // See more about glitch effect there: https://en.wikipedia.org/wiki/Reactive_programming#Glitches or https://blog.strongbrew.io/combine-latest-glitch/ 41 | 42 | ngOnChanges(changes: CustomSimpleChanges): void { 43 | const name: string | null = changes.userName.currentValue; 44 | console.log('name inside ngOnChanges was changed', name); 45 | if (name) { 46 | this.firstName = name; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/src/app/data-facade/_services/facade/animal-ngxs.facade.ts: -------------------------------------------------------------------------------- 1 | import { AnimalFacade } from './animal.facade'; 2 | import { Actions, ofActionCompleted, ofActionDispatched, Store } from '@ngxs/store'; 3 | import { map, shareReplay, startWith } from 'rxjs/operators'; 4 | import { merge, Observable } from 'rxjs'; 5 | import { AnimalState } from '../../_store/states/animal-state'; 6 | import { AnimalStateModel } from '../../_store/models/animal-state'; 7 | import { AddAnimal, ResetAnimals } from '../../_store/states/animal.actions'; 8 | import { Injectable } from '@angular/core'; 9 | import { StatusData } from '../../_models/status-data'; 10 | 11 | @Injectable() 12 | export class AnimalNgxsFacade extends AnimalFacade { 13 | private addAnimalStatus$!: Observable; 14 | constructor(private store: Store, private actions$: Actions) { 15 | super(); 16 | 17 | this.initAnimalAddStatus(); 18 | } 19 | 20 | public addAnimal(animal: string): void { 21 | this.store.dispatch(new AddAnimal(animal)); 22 | } 23 | 24 | public getAddAnimalStatus(): Observable { 25 | return this.addAnimalStatus$; 26 | } 27 | 28 | public getAnimals(): Observable { 29 | return this.store.select(AnimalState.selectAnimals); 30 | } 31 | 32 | public resetAnimals(): void { 33 | this.store.dispatch(new ResetAnimals()); 34 | } 35 | 36 | public getAnimalStateModel(): Observable { 37 | return this.store.select(AnimalState.selectState); 38 | } 39 | 40 | // Example how to use state without store data inside 41 | private initAnimalAddStatus(): void { 42 | const actionCompleted$ = this.actions$.pipe( 43 | ofActionCompleted(AddAnimal), 44 | map((status: { result: { successful: any; canceled: any } }) => { 45 | if (status.result.successful) { 46 | return StatusData.LOADED; 47 | } 48 | if (status.result.canceled) { 49 | return StatusData.CANCEL; 50 | } 51 | return StatusData.ERROR; 52 | }), 53 | startWith(StatusData.PENDING) 54 | ); 55 | 56 | const actionDispatched$ = this.actions$.pipe( 57 | ofActionDispatched(AddAnimal), 58 | map(() => { 59 | return StatusData.LOADING; 60 | }) 61 | ); 62 | 63 | this.addAnimalStatus$ = merge(actionCompleted$, actionDispatched$).pipe(shareReplay(1)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /examples/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | /*************************************************************************************************** 63 | * APPLICATION IMPORTS 64 | */ 65 | -------------------------------------------------------------------------------- /examples/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "rxjs-tslint-rules"], 3 | "rulesDirectory": ["codelyzer"], 4 | "rules": { 5 | "interface-name": [true, "always-prefix"], // for Interface Name 6 | "align": { 7 | "options": ["parameters", "statements"] 8 | }, 9 | "array-type": false, 10 | "arrow-return-shorthand": true, 11 | "curly": true, 12 | "deprecation": { 13 | "severity": "warning" 14 | }, 15 | "eofline": true, 16 | "import-blacklist": [true, "rxjs/Rx"], 17 | "import-spacing": true, 18 | "indent": { 19 | "options": ["spaces"] 20 | }, 21 | "max-classes-per-file": false, 22 | "max-line-length": [true, 140], 23 | "member-ordering": [ 24 | true, 25 | { 26 | "order": ["static-field", "instance-field", "static-method", "instance-method"] 27 | } 28 | ], 29 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"], 30 | "no-empty": false, 31 | "no-inferrable-types": [true, "ignore-params"], 32 | "no-non-null-assertion": true, 33 | "no-redundant-jsdoc": true, 34 | "no-switch-case-fall-through": true, 35 | "no-var-requires": false, 36 | "object-literal-key-quotes": [true, "as-needed"], 37 | "quotemark": [true, "single"], 38 | "semicolon": { 39 | "options": ["always"] 40 | }, 41 | "space-before-function-paren": { 42 | "options": { 43 | "anonymous": "never", 44 | "asyncArrow": "always", 45 | "constructor": "never", 46 | "method": "never", 47 | "named": "never" 48 | } 49 | }, 50 | "typedef": [true, "call-signature"], 51 | "typedef-whitespace": { 52 | "options": [ 53 | { 54 | "call-signature": "nospace", 55 | "index-signature": "nospace", 56 | "parameter": "nospace", 57 | "property-declaration": "nospace", 58 | "variable-declaration": "nospace" 59 | }, 60 | { 61 | "call-signature": "onespace", 62 | "index-signature": "onespace", 63 | "parameter": "onespace", 64 | "property-declaration": "onespace", 65 | "variable-declaration": "onespace" 66 | } 67 | ] 68 | }, 69 | "variable-name": { 70 | "options": ["ban-keywords", "check-format", "allow-pascal-case"] 71 | }, 72 | "whitespace": { 73 | "options": ["check-branch", "check-decl", "check-operator", "check-separator", "check-type", "check-typecast"] 74 | }, 75 | "component-class-suffix": true, 76 | "contextual-lifecycle": true, 77 | "directive-class-suffix": true, 78 | "no-conflicting-lifecycle": true, 79 | "no-host-metadata-property": true, 80 | "no-input-rename": true, 81 | "no-inputs-metadata-property": true, 82 | "no-output-native": true, 83 | "no-output-on-prefix": true, 84 | "no-output-rename": true, 85 | "no-outputs-metadata-property": true, 86 | "template-banana-in-box": true, 87 | "template-no-negated-async": true, 88 | "use-lifecycle-interface": true, 89 | "use-pipe-transform-interface": true, 90 | "directive-selector": [true, "attribute", "app", "camelCase"], 91 | "component-selector": [true, "element", "app", "kebab-case"], 92 | "rxjs-no-unsafe-takeuntil": { 93 | "severity": "error" 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /examples/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 17 | 18 | 28 | 29 | 32 | 33 | 40 | 41 | 48 | 49 | 61 | 62 | 67 | 68 | -------------------------------------------------------------------------------- /examples/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { AppComponent } from './app.component'; 4 | import { ShowMockUsageComponent } from './components/show-mock-usage/show-mock-usage.component'; 5 | import { LoggerServiceProvider } from './providers/logger-service.provider'; 6 | import { TslintWrongTakeuntilRuleComponent } from './components/tslint-wrong-takeuntil-rule/tslint-wrong-takeuntil-rule.component'; 7 | import { TrackByExampleComponent } from './components/track-by-example/track-by-example.component'; 8 | import { DisplayBlockByDefaultComponent } from './components/display-block-by-default/display-block-by-default'; 9 | import { ChangeDetectionByDefaultComponent } from './components/change-detection-by-default/change-detection-by-default.component'; 10 | import { SmartComponent } from './components/smart-dumb-concept/_smart/smart.component'; 11 | import { DumbOneComponent } from './components/smart-dumb-concept/_dumb/dumb-one/dumb-one.component'; 12 | import { DumbTwoComponent } from './components/smart-dumb-concept/_dumb/dumb-two/dumb-two.component'; 13 | import { DumbThreeComponent } from './components/smart-dumb-concept/_dumb/dumb-three/dumb-three.component'; 14 | import { DumbFourComponent } from './components/smart-dumb-concept/_dumb/dumb-four/dumb-four.component'; 15 | import { DumbFiveComponent } from './components/smart-dumb-concept/_dumb/dumb-five/dumb-five.component'; 16 | import { UserInfoComponent } from './components/project-folder-sturcture/user-info/_components/_smart/user-info/user-info.component'; 17 | import { UserInfoDetailsComponent } from './components/project-folder-sturcture/user-info/_components/_dumb/user-info-details/user-info-details.component'; 18 | import { PropertyChangesDetectionComponent } from './components/input-changes-detection/property-changes-detection/property-changes-detection.component'; 19 | import { PropertyChangeComponent } from './components/input-changes-detection/property-change/property-change.component'; 20 | import { FormsModule } from '@angular/forms'; 21 | import { UnsubscribeComponent } from './components/how-to-unsubscribe/unsubscribe.component'; 22 | import { DataFacadeModule } from './data-facade/data-facade.module'; 23 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 24 | import { DialogServiceModule } from './dialog-as-service/dialog-service.module'; 25 | import { HttpProxyModule } from './components/http-proxy-example/http-proxy.module'; 26 | import {UnsubscribeService} from "./service/unsubscribe.service"; 27 | 28 | @NgModule({ 29 | declarations: [ 30 | AppComponent, 31 | ShowMockUsageComponent, 32 | TslintWrongTakeuntilRuleComponent, 33 | TrackByExampleComponent, 34 | DisplayBlockByDefaultComponent, 35 | ChangeDetectionByDefaultComponent, 36 | SmartComponent, 37 | DumbOneComponent, 38 | DumbTwoComponent, 39 | DumbThreeComponent, 40 | DumbFourComponent, 41 | DumbFiveComponent, 42 | UserInfoComponent, 43 | UserInfoDetailsComponent, 44 | PropertyChangesDetectionComponent, 45 | PropertyChangeComponent, 46 | UnsubscribeComponent, 47 | ], 48 | imports: [ 49 | BrowserModule, 50 | FormsModule, 51 | DataFacadeModule, 52 | DataFacadeModule, 53 | BrowserAnimationsModule, 54 | DialogServiceModule, 55 | HttpProxyModule, 56 | ], 57 | providers: [LoggerServiceProvider, UnsubscribeService], 58 | bootstrap: [AppComponent], 59 | }) 60 | export class AppModule {} 61 | -------------------------------------------------------------------------------- /examples/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-best-practicies": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:application": { 10 | "strict": true 11 | }, 12 | "@schematics/angular:component": { 13 | "displayBlock": true, 14 | "changeDetection": "OnPush" 15 | } 16 | }, 17 | "root": "", 18 | "sourceRoot": "src", 19 | "prefix": "app", 20 | "architect": { 21 | "build": { 22 | "builder": "@angular-devkit/build-angular:browser", 23 | "options": { 24 | "outputPath": "dist/angular-best-practicies", 25 | "index": "src/index.html", 26 | "main": "src/main.ts", 27 | "polyfills": "src/polyfills.ts", 28 | "tsConfig": "tsconfig.app.json", 29 | "aot": true, 30 | "assets": ["src/favicon.ico", "src/assets"], 31 | "styles": ["./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.css"], 32 | "scripts": [] 33 | }, 34 | "configurations": { 35 | "production": { 36 | "fileReplacements": [ 37 | { 38 | "replace": "src/environments/environment.ts", 39 | "with": "src/environments/environment.prod.ts" 40 | } 41 | ], 42 | "optimization": true, 43 | "outputHashing": "all", 44 | "sourceMap": false, 45 | "namedChunks": false, 46 | "extractLicenses": true, 47 | "vendorChunk": false, 48 | "buildOptimizer": true, 49 | "budgets": [ 50 | { 51 | "type": "initial", 52 | "maximumWarning": "500kb", 53 | "maximumError": "1mb" 54 | }, 55 | { 56 | "type": "anyComponentStyle", 57 | "maximumWarning": "2kb", 58 | "maximumError": "4kb" 59 | } 60 | ] 61 | } 62 | } 63 | }, 64 | "serve": { 65 | "builder": "@angular-devkit/build-angular:dev-server", 66 | "options": { 67 | "browserTarget": "angular-best-practicies:build", 68 | "proxyConfig": "proxy.conf.json" 69 | }, 70 | "configurations": { 71 | "production": { 72 | "browserTarget": "angular-best-practicies:build:production" 73 | } 74 | } 75 | }, 76 | "extract-i18n": { 77 | "builder": "@angular-devkit/build-angular:extract-i18n", 78 | "options": { 79 | "browserTarget": "angular-best-practicies:build" 80 | } 81 | }, 82 | "test": { 83 | "builder": "@angular-devkit/build-angular:karma", 84 | "options": { 85 | "main": "src/test.ts", 86 | "polyfills": "src/polyfills.ts", 87 | "tsConfig": "tsconfig.spec.json", 88 | "karmaConfig": "karma.conf.js", 89 | "assets": ["src/favicon.ico", "src/assets"], 90 | "styles": ["./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.css"], 91 | "scripts": [] 92 | } 93 | }, 94 | "lint": { 95 | "builder": "@angular-devkit/build-angular:tslint", 96 | "options": { 97 | "tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json"], 98 | "exclude": ["**/node_modules/**"] 99 | } 100 | }, 101 | "e2e": { 102 | "builder": "@angular-devkit/build-angular:protractor", 103 | "options": { 104 | "protractorConfig": "e2e/protractor.conf.js", 105 | "devServerTarget": "angular-best-practicies:serve" 106 | }, 107 | "configurations": { 108 | "production": { 109 | "devServerTarget": "angular-best-practicies:serve:production" 110 | } 111 | } 112 | } 113 | } 114 | } 115 | }, 116 | "defaultProject": "angular-best-practicies" 117 | } 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /examples/dist/angular-best-practicies/3rdpartylicenses.txt: -------------------------------------------------------------------------------- 1 | @angular/common 2 | MIT 3 | 4 | @angular/core 5 | MIT 6 | 7 | @angular/platform-browser 8 | MIT 9 | 10 | rxjs 11 | Apache-2.0 12 | Apache License 13 | Version 2.0, January 2004 14 | http://www.apache.org/licenses/ 15 | 16 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 17 | 18 | 1. Definitions. 19 | 20 | "License" shall mean the terms and conditions for use, reproduction, 21 | and distribution as defined by Sections 1 through 9 of this document. 22 | 23 | "Licensor" shall mean the copyright owner or entity authorized by 24 | the copyright owner that is granting the License. 25 | 26 | "Legal Entity" shall mean the union of the acting entity and all 27 | other entities that control, are controlled by, or are under common 28 | control with that entity. For the purposes of this definition, 29 | "control" means (i) the power, direct or indirect, to cause the 30 | direction or management of such entity, whether by contract or 31 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 32 | outstanding shares, or (iii) beneficial ownership of such entity. 33 | 34 | "You" (or "Your") shall mean an individual or Legal Entity 35 | exercising permissions granted by this License. 36 | 37 | "Source" form shall mean the preferred form for making modifications, 38 | including but not limited to software source code, documentation 39 | source, and configuration files. 40 | 41 | "Object" form shall mean any form resulting from mechanical 42 | transformation or translation of a Source form, including but 43 | not limited to compiled object code, generated documentation, 44 | and conversions to other media types. 45 | 46 | "Work" shall mean the work of authorship, whether in Source or 47 | Object form, made available under the License, as indicated by a 48 | copyright notice that is included in or attached to the work 49 | (an example is provided in the Appendix below). 50 | 51 | "Derivative Works" shall mean any work, whether in Source or Object 52 | form, that is based on (or derived from) the Work and for which the 53 | editorial revisions, annotations, elaborations, or other modifications 54 | represent, as a whole, an original work of authorship. For the purposes 55 | of this License, Derivative Works shall not include works that remain 56 | separable from, or merely link (or bind by name) to the interfaces of, 57 | the Work and Derivative Works thereof. 58 | 59 | "Contribution" shall mean any work of authorship, including 60 | the original version of the Work and any modifications or additions 61 | to that Work or Derivative Works thereof, that is intentionally 62 | submitted to Licensor for inclusion in the Work by the copyright owner 63 | or by an individual or Legal Entity authorized to submit on behalf of 64 | the copyright owner. For the purposes of this definition, "submitted" 65 | means any form of electronic, verbal, or written communication sent 66 | to the Licensor or its representatives, including but not limited to 67 | communication on electronic mailing lists, source code control systems, 68 | and issue tracking systems that are managed by, or on behalf of, the 69 | Licensor for the purpose of discussing and improving the Work, but 70 | excluding communication that is conspicuously marked or otherwise 71 | designated in writing by the copyright owner as "Not a Contribution." 72 | 73 | "Contributor" shall mean Licensor and any individual or Legal Entity 74 | on behalf of whom a Contribution has been received by Licensor and 75 | subsequently incorporated within the Work. 76 | 77 | 2. Grant of Copyright License. Subject to the terms and conditions of 78 | this License, each Contributor hereby grants to You a perpetual, 79 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 80 | copyright license to reproduce, prepare Derivative Works of, 81 | publicly display, publicly perform, sublicense, and distribute the 82 | Work and such Derivative Works in Source or Object form. 83 | 84 | 3. Grant of Patent License. Subject to the terms and conditions of 85 | this License, each Contributor hereby grants to You a perpetual, 86 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 87 | (except as stated in this section) patent license to make, have made, 88 | use, offer to sell, sell, import, and otherwise transfer the Work, 89 | where such license applies only to those patent claims licensable 90 | by such Contributor that are necessarily infringed by their 91 | Contribution(s) alone or by combination of their Contribution(s) 92 | with the Work to which such Contribution(s) was submitted. If You 93 | institute patent litigation against any entity (including a 94 | cross-claim or counterclaim in a lawsuit) alleging that the Work 95 | or a Contribution incorporated within the Work constitutes direct 96 | or contributory patent infringement, then any patent licenses 97 | granted to You under this License for that Work shall terminate 98 | as of the date such litigation is filed. 99 | 100 | 4. Redistribution. You may reproduce and distribute copies of the 101 | Work or Derivative Works thereof in any medium, with or without 102 | modifications, and in Source or Object form, provided that You 103 | meet the following conditions: 104 | 105 | (a) You must give any other recipients of the Work or 106 | Derivative Works a copy of this License; and 107 | 108 | (b) You must cause any modified files to carry prominent notices 109 | stating that You changed the files; and 110 | 111 | (c) You must retain, in the Source form of any Derivative Works 112 | that You distribute, all copyright, patent, trademark, and 113 | attribution notices from the Source form of the Work, 114 | excluding those notices that do not pertain to any part of 115 | the Derivative Works; and 116 | 117 | (d) If the Work includes a "NOTICE" text file as part of its 118 | distribution, then any Derivative Works that You distribute must 119 | include a readable copy of the attribution notices contained 120 | within such NOTICE file, excluding those notices that do not 121 | pertain to any part of the Derivative Works, in at least one 122 | of the following places: within a NOTICE text file distributed 123 | as part of the Derivative Works; within the Source form or 124 | documentation, if provided along with the Derivative Works; or, 125 | within a display generated by the Derivative Works, if and 126 | wherever such third-party notices normally appear. The contents 127 | of the NOTICE file are for informational purposes only and 128 | do not modify the License. You may add Your own attribution 129 | notices within Derivative Works that You distribute, alongside 130 | or as an addendum to the NOTICE text from the Work, provided 131 | that such additional attribution notices cannot be construed 132 | as modifying the License. 133 | 134 | You may add Your own copyright statement to Your modifications and 135 | may provide additional or different license terms and conditions 136 | for use, reproduction, or distribution of Your modifications, or 137 | for any such Derivative Works as a whole, provided Your use, 138 | reproduction, and distribution of the Work otherwise complies with 139 | the conditions stated in this License. 140 | 141 | 5. Submission of Contributions. Unless You explicitly state otherwise, 142 | any Contribution intentionally submitted for inclusion in the Work 143 | by You to the Licensor shall be under the terms and conditions of 144 | this License, without any additional terms or conditions. 145 | Notwithstanding the above, nothing herein shall supersede or modify 146 | the terms of any separate license agreement you may have executed 147 | with Licensor regarding such Contributions. 148 | 149 | 6. Trademarks. This License does not grant permission to use the trade 150 | names, trademarks, service marks, or product names of the Licensor, 151 | except as required for reasonable and customary use in describing the 152 | origin of the Work and reproducing the content of the NOTICE file. 153 | 154 | 7. Disclaimer of Warranty. Unless required by applicable law or 155 | agreed to in writing, Licensor provides the Work (and each 156 | Contributor provides its Contributions) on an "AS IS" BASIS, 157 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 158 | implied, including, without limitation, any warranties or conditions 159 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 160 | PARTICULAR PURPOSE. You are solely responsible for determining the 161 | appropriateness of using or redistributing the Work and assume any 162 | risks associated with Your exercise of permissions under this License. 163 | 164 | 8. Limitation of Liability. In no event and under no legal theory, 165 | whether in tort (including negligence), contract, or otherwise, 166 | unless required by applicable law (such as deliberate and grossly 167 | negligent acts) or agreed to in writing, shall any Contributor be 168 | liable to You for damages, including any direct, indirect, special, 169 | incidental, or consequential damages of any character arising as a 170 | result of this License or out of the use or inability to use the 171 | Work (including but not limited to damages for loss of goodwill, 172 | work stoppage, computer failure or malfunction, or any and all 173 | other commercial damages or losses), even if such Contributor 174 | has been advised of the possibility of such damages. 175 | 176 | 9. Accepting Warranty or Additional Liability. While redistributing 177 | the Work or Derivative Works thereof, You may choose to offer, 178 | and charge a fee for, acceptance of support, warranty, indemnity, 179 | or other liability obligations and/or rights consistent with this 180 | License. However, in accepting such obligations, You may act only 181 | on Your own behalf and on Your sole responsibility, not on behalf 182 | of any other Contributor, and only if You agree to indemnify, 183 | defend, and hold each Contributor harmless for any liability 184 | incurred by, or claims asserted against, such Contributor by reason 185 | of your accepting any such warranty or additional liability. 186 | 187 | END OF TERMS AND CONDITIONS 188 | 189 | APPENDIX: How to apply the Apache License to your work. 190 | 191 | To apply the Apache License to your work, attach the following 192 | boilerplate notice, with the fields enclosed by brackets "[]" 193 | replaced with your own identifying information. (Don't include 194 | the brackets!) The text should be enclosed in the appropriate 195 | comment syntax for the file format. We also recommend that a 196 | file or class name and description of purpose be included on the 197 | same "printed page" as the copyright notice for easier 198 | identification within third-party archives. 199 | 200 | Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors 201 | 202 | Licensed under the Apache License, Version 2.0 (the "License"); 203 | you may not use this file except in compliance with the License. 204 | You may obtain a copy of the License at 205 | 206 | http://www.apache.org/licenses/LICENSE-2.0 207 | 208 | Unless required by applicable law or agreed to in writing, software 209 | distributed under the License is distributed on an "AS IS" BASIS, 210 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 211 | See the License for the specific language governing permissions and 212 | limitations under the License. 213 | 214 | 215 | 216 | zone.js 217 | MIT 218 | The MIT License 219 | 220 | Copyright (c) 2010-2020 Google LLC. https://angular.io/license 221 | 222 | Permission is hereby granted, free of charge, to any person obtaining a copy 223 | of this software and associated documentation files (the "Software"), to deal 224 | in the Software without restriction, including without limitation the rights 225 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 226 | copies of the Software, and to permit persons to whom the Software is 227 | furnished to do so, subject to the following conditions: 228 | 229 | The above copyright notice and this permission notice shall be included in 230 | all copies or substantial portions of the Software. 231 | 232 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 233 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 234 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 235 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 236 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 237 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 238 | THE SOFTWARE. 239 | -------------------------------------------------------------------------------- /examples/dist/angular-best-practicies/polyfills.94daefd414b8355106ab.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[2],{1:function(e,t,n){e.exports=n("hN/g")},"hN/g":function(e,t,n){"use strict";n.r(t),n("pDpN")},pDpN:function(e,t,n){"use strict";!function(e){const t=e.performance;function n(e){t&&t.mark&&t.mark(e)}function o(e,n){t&&t.measure&&t.measure(e,n)}n("Zone");const r=e.__Zone_symbol_prefix||"__zone_symbol__";function s(e){return r+e}const a=!0===e[s("forceDuplicateZoneCheck")];if(e.Zone){if(a||"function"!=typeof e.Zone.__symbol__)throw new Error("Zone already loaded.");return e.Zone}class i{constructor(e,t){this._parent=e,this._name=t?t.name||"unnamed":"",this._properties=t&&t.properties||{},this._zoneDelegate=new l(this,this._parent&&this._parent._zoneDelegate,t)}static assertZonePatched(){if(e.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")}static get root(){let e=i.current;for(;e.parent;)e=e.parent;return e}static get current(){return z.zone}static get currentTask(){return j}static __load_patch(t,r,s=!1){if(O.hasOwnProperty(t)){if(!s&&a)throw Error("Already loaded patch: "+t)}else if(!e["__Zone_disable_"+t]){const s="Zone:"+t;n(s),O[t]=r(e,i,C),o(s,s)}}get parent(){return this._parent}get name(){return this._name}get(e){const t=this.getZoneWith(e);if(t)return t._properties[e]}getZoneWith(e){let t=this;for(;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null}fork(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)}wrap(e,t){if("function"!=typeof e)throw new Error("Expecting function got: "+e);const n=this._zoneDelegate.intercept(this,e,t),o=this;return function(){return o.runGuarded(n,this,arguments,t)}}run(e,t,n,o){z={parent:z,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,o)}finally{z=z.parent}}runGuarded(e,t=null,n,o){z={parent:z,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,o)}catch(r){if(this._zoneDelegate.handleError(this,r))throw r}}finally{z=z.parent}}runTask(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||y).name+"; Execution: "+this.name+")");if(e.state===v&&(e.type===P||e.type===D))return;const o=e.state!=E;o&&e._transitionTo(E,b),e.runCount++;const r=j;j=e,z={parent:z,zone:this};try{e.type==D&&e.data&&!e.data.isPeriodic&&(e.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(s){if(this._zoneDelegate.handleError(this,s))throw s}}finally{e.state!==v&&e.state!==Z&&(e.type==P||e.data&&e.data.isPeriodic?o&&e._transitionTo(b,E):(e.runCount=0,this._updateTaskCount(e,-1),o&&e._transitionTo(v,E,v))),z=z.parent,j=r}}scheduleTask(e){if(e.zone&&e.zone!==this){let t=this;for(;t;){if(t===e.zone)throw Error(`can not reschedule task to ${this.name} which is descendants of the original zone ${e.zone.name}`);t=t.parent}}e._transitionTo(T,v);const t=[];e._zoneDelegates=t,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(n){throw e._transitionTo(Z,T,v),this._zoneDelegate.handleError(this,n),n}return e._zoneDelegates===t&&this._updateTaskCount(e,1),e.state==T&&e._transitionTo(b,T),e}scheduleMicroTask(e,t,n,o){return this.scheduleTask(new u(S,e,t,n,o,void 0))}scheduleMacroTask(e,t,n,o,r){return this.scheduleTask(new u(D,e,t,n,o,r))}scheduleEventTask(e,t,n,o,r){return this.scheduleTask(new u(P,e,t,n,o,r))}cancelTask(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||y).name+"; Execution: "+this.name+")");e._transitionTo(w,b,E);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(Z,w),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(v,w),e.runCount=0,e}_updateTaskCount(e,t){const n=e._zoneDelegates;-1==t&&(e._zoneDelegates=null);for(let o=0;oe.hasTask(n,o),onScheduleTask:(e,t,n,o)=>e.scheduleTask(n,o),onInvokeTask:(e,t,n,o,r,s)=>e.invokeTask(n,o,r,s),onCancelTask:(e,t,n,o)=>e.cancelTask(n,o)};class l{constructor(e,t,n){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this.zone=e,this._parentDelegate=t,this._forkZS=n&&(n&&n.onFork?n:t._forkZS),this._forkDlgt=n&&(n.onFork?t:t._forkDlgt),this._forkCurrZone=n&&(n.onFork?this.zone:t._forkCurrZone),this._interceptZS=n&&(n.onIntercept?n:t._interceptZS),this._interceptDlgt=n&&(n.onIntercept?t:t._interceptDlgt),this._interceptCurrZone=n&&(n.onIntercept?this.zone:t._interceptCurrZone),this._invokeZS=n&&(n.onInvoke?n:t._invokeZS),this._invokeDlgt=n&&(n.onInvoke?t:t._invokeDlgt),this._invokeCurrZone=n&&(n.onInvoke?this.zone:t._invokeCurrZone),this._handleErrorZS=n&&(n.onHandleError?n:t._handleErrorZS),this._handleErrorDlgt=n&&(n.onHandleError?t:t._handleErrorDlgt),this._handleErrorCurrZone=n&&(n.onHandleError?this.zone:t._handleErrorCurrZone),this._scheduleTaskZS=n&&(n.onScheduleTask?n:t._scheduleTaskZS),this._scheduleTaskDlgt=n&&(n.onScheduleTask?t:t._scheduleTaskDlgt),this._scheduleTaskCurrZone=n&&(n.onScheduleTask?this.zone:t._scheduleTaskCurrZone),this._invokeTaskZS=n&&(n.onInvokeTask?n:t._invokeTaskZS),this._invokeTaskDlgt=n&&(n.onInvokeTask?t:t._invokeTaskDlgt),this._invokeTaskCurrZone=n&&(n.onInvokeTask?this.zone:t._invokeTaskCurrZone),this._cancelTaskZS=n&&(n.onCancelTask?n:t._cancelTaskZS),this._cancelTaskDlgt=n&&(n.onCancelTask?t:t._cancelTaskDlgt),this._cancelTaskCurrZone=n&&(n.onCancelTask?this.zone:t._cancelTaskCurrZone),this._hasTaskZS=null,this._hasTaskDlgt=null,this._hasTaskDlgtOwner=null,this._hasTaskCurrZone=null;const o=n&&n.onHasTask;(o||t&&t._hasTaskZS)&&(this._hasTaskZS=o?n:c,this._hasTaskDlgt=t,this._hasTaskDlgtOwner=this,this._hasTaskCurrZone=e,n.onScheduleTask||(this._scheduleTaskZS=c,this._scheduleTaskDlgt=t,this._scheduleTaskCurrZone=this.zone),n.onInvokeTask||(this._invokeTaskZS=c,this._invokeTaskDlgt=t,this._invokeTaskCurrZone=this.zone),n.onCancelTask||(this._cancelTaskZS=c,this._cancelTaskDlgt=t,this._cancelTaskCurrZone=this.zone))}fork(e,t){return this._forkZS?this._forkZS.onFork(this._forkDlgt,this.zone,e,t):new i(e,t)}intercept(e,t,n){return this._interceptZS?this._interceptZS.onIntercept(this._interceptDlgt,this._interceptCurrZone,e,t,n):t}invoke(e,t,n,o,r){return this._invokeZS?this._invokeZS.onInvoke(this._invokeDlgt,this._invokeCurrZone,e,t,n,o,r):t.apply(n,o)}handleError(e,t){return!this._handleErrorZS||this._handleErrorZS.onHandleError(this._handleErrorDlgt,this._handleErrorCurrZone,e,t)}scheduleTask(e,t){let n=t;if(this._scheduleTaskZS)this._hasTaskZS&&n._zoneDelegates.push(this._hasTaskDlgtOwner),n=this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt,this._scheduleTaskCurrZone,e,t),n||(n=t);else if(t.scheduleFn)t.scheduleFn(t);else{if(t.type!=S)throw new Error("Task is missing scheduleFn.");k(t)}return n}invokeTask(e,t,n,o){return this._invokeTaskZS?this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt,this._invokeTaskCurrZone,e,t,n,o):t.callback.apply(n,o)}cancelTask(e,t){let n;if(this._cancelTaskZS)n=this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt,this._cancelTaskCurrZone,e,t);else{if(!t.cancelFn)throw Error("Task is not cancelable");n=t.cancelFn(t)}return n}hasTask(e,t){try{this._hasTaskZS&&this._hasTaskZS.onHasTask(this._hasTaskDlgt,this._hasTaskCurrZone,e,t)}catch(n){this.handleError(e,n)}}_updateTaskCount(e,t){const n=this._taskCounts,o=n[e],r=n[e]=o+t;if(r<0)throw new Error("More tasks executed then were scheduled.");0!=o&&0!=r||this.hasTask(this.zone,{microTask:n.microTask>0,macroTask:n.macroTask>0,eventTask:n.eventTask>0,change:e})}}class u{constructor(t,n,o,r,s,a){if(this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=t,this.source=n,this.data=r,this.scheduleFn=s,this.cancelFn=a,!o)throw new Error("callback is not defined");this.callback=o;const i=this;this.invoke=t===P&&r&&r.useG?u.invokeTask:function(){return u.invokeTask.call(e,i,this,arguments)}}static invokeTask(e,t,n){e||(e=this),I++;try{return e.runCount++,e.zone.runTask(e,t,n)}finally{1==I&&m(),I--}}get zone(){return this._zone}get state(){return this._state}cancelScheduleRequest(){this._transitionTo(v,T)}_transitionTo(e,t,n){if(this._state!==t&&this._state!==n)throw new Error(`${this.type} '${this.source}': can not transition to '${e}', expecting state '${t}'${n?" or '"+n+"'":""}, was '${this._state}'.`);this._state=e,e==v&&(this._zoneDelegates=null)}toString(){return this.data&&void 0!==this.data.handleId?this.data.handleId.toString():Object.prototype.toString.call(this)}toJSON(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}}}const h=s("setTimeout"),p=s("Promise"),f=s("then");let d,g=[],_=!1;function k(t){if(0===I&&0===g.length)if(d||e[p]&&(d=e[p].resolve(0)),d){let e=d[f];e||(e=d.then),e.call(d,m)}else e[h](m,0);t&&g.push(t)}function m(){if(!_){for(_=!0;g.length;){const t=g;g=[];for(let n=0;nz,onUnhandledError:R,microtaskDrainDone:R,scheduleMicroTask:k,showUncaughtError:()=>!i[s("ignoreConsoleErrorUncaughtError")],patchEventTarget:()=>[],patchOnProperties:R,patchMethod:()=>R,bindArguments:()=>[],patchThen:()=>R,patchMacroTask:()=>R,patchEventPrototype:()=>R,isIEOrEdge:()=>!1,getGlobalObjects:()=>{},ObjectDefineProperty:()=>R,ObjectGetOwnPropertyDescriptor:()=>{},ObjectCreate:()=>{},ArraySlice:()=>[],patchClass:()=>R,wrapWithCurrentZone:()=>R,filterProperties:()=>[],attachOriginToPatched:()=>R,_redefineProperty:()=>R,patchCallbacks:()=>R};let z={parent:null,zone:new i(null,null)},j=null,I=0;function R(){}o("Zone","Zone"),e.Zone=i}("undefined"!=typeof window&&window||"undefined"!=typeof self&&self||global);const o=Object.getOwnPropertyDescriptor,r=Object.defineProperty,s=Object.getPrototypeOf,a=Object.create,i=Array.prototype.slice,c="addEventListener",l="removeEventListener",u=Zone.__symbol__(c),h=Zone.__symbol__(l),p="true",f="false",d=Zone.__symbol__("");function g(e,t){return Zone.current.wrap(e,t)}function _(e,t,n,o,r){return Zone.current.scheduleMacroTask(e,t,n,o,r)}const k=Zone.__symbol__,m="undefined"!=typeof window,y=m?window:void 0,v=m&&y||"object"==typeof self&&self||global,T=[null];function b(e,t){for(let n=e.length-1;n>=0;n--)"function"==typeof e[n]&&(e[n]=g(e[n],t+"_"+n));return e}function E(e){return!e||!1!==e.writable&&!("function"==typeof e.get&&void 0===e.set)}const w="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,Z=!("nw"in v)&&void 0!==v.process&&"[object process]"==={}.toString.call(v.process),S=!Z&&!w&&!(!m||!y.HTMLElement),D=void 0!==v.process&&"[object process]"==={}.toString.call(v.process)&&!w&&!(!m||!y.HTMLElement),P={},O=function(e){if(!(e=e||v.event))return;let t=P[e.type];t||(t=P[e.type]=k("ON_PROPERTY"+e.type));const n=this||e.target||v,o=n[t];let r;if(S&&n===y&&"error"===e.type){const t=e;r=o&&o.call(this,t.message,t.filename,t.lineno,t.colno,t.error),!0===r&&e.preventDefault()}else r=o&&o.apply(this,arguments),null==r||r||e.preventDefault();return r};function C(e,t,n){let s=o(e,t);if(!s&&n&&o(n,t)&&(s={enumerable:!0,configurable:!0}),!s||!s.configurable)return;const a=k("on"+t+"patched");if(e.hasOwnProperty(a)&&e[a])return;delete s.writable,delete s.value;const i=s.get,c=s.set,l=t.substr(2);let u=P[l];u||(u=P[l]=k("ON_PROPERTY"+l)),s.set=function(t){let n=this;n||e!==v||(n=v),n&&(n[u]&&n.removeEventListener(l,O),c&&c.apply(n,T),"function"==typeof t?(n[u]=t,n.addEventListener(l,O,!1)):n[u]=null)},s.get=function(){let n=this;if(n||e!==v||(n=v),!n)return null;const o=n[u];if(o)return o;if(i){let e=i&&i.call(this);if(e)return s.set.call(this,e),"function"==typeof n.removeAttribute&&n.removeAttribute(t),e}return null},r(e,t,s),e[a]=!0}function z(e,t,n){if(t)for(let o=0;ofunction(t,o){const s=n(t,o);return s.cbIdx>=0&&"function"==typeof o[s.cbIdx]?_(s.name,o[s.cbIdx],s,r):e.apply(t,o)})}function N(e,t){e[k("OriginalDelegate")]=t}let x=!1,L=!1;function A(){try{const e=y.navigator.userAgent;if(-1!==e.indexOf("MSIE ")||-1!==e.indexOf("Trident/"))return!0}catch(e){}return!1}function H(){if(x)return L;x=!0;try{const e=y.navigator.userAgent;-1===e.indexOf("MSIE ")&&-1===e.indexOf("Trident/")&&-1===e.indexOf("Edge/")||(L=!0)}catch(e){}return L}Zone.__load_patch("ZoneAwarePromise",(e,t,n)=>{const o=Object.getOwnPropertyDescriptor,r=Object.defineProperty,s=n.symbol,a=[],i=!0===e[s("DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION")],c=s("Promise"),l=s("then");n.onUnhandledError=e=>{if(n.showUncaughtError()){const t=e&&e.rejection;t?console.error("Unhandled Promise rejection:",t instanceof Error?t.message:t,"; Zone:",e.zone.name,"; Task:",e.task&&e.task.source,"; Value:",t,t instanceof Error?t.stack:void 0):console.error(e)}},n.microtaskDrainDone=()=>{for(;a.length;){const t=a.shift();try{t.zone.runGuarded(()=>{if(t.throwOriginal)throw t.rejection;throw t})}catch(e){h(e)}}};const u=s("unhandledPromiseRejectionHandler");function h(e){n.onUnhandledError(e);try{const n=t[u];"function"==typeof n&&n.call(this,e)}catch(o){}}function p(e){return e&&e.then}function f(e){return e}function d(e){return C.reject(e)}const g=s("state"),_=s("value"),k=s("finally"),m=s("parentPromiseValue"),y=s("parentPromiseState"),v=null,T=!0,b=!1;function E(e,t){return n=>{try{Z(e,t,n)}catch(o){Z(e,!1,o)}}}const w=s("currentTaskTrace");function Z(e,o,s){const c=function(){let e=!1;return function(t){return function(){e||(e=!0,t.apply(null,arguments))}}}();if(e===s)throw new TypeError("Promise resolved with itself");if(e[g]===v){let h=null;try{"object"!=typeof s&&"function"!=typeof s||(h=s&&s.then)}catch(u){return c(()=>{Z(e,!1,u)})(),e}if(o!==b&&s instanceof C&&s.hasOwnProperty(g)&&s.hasOwnProperty(_)&&s[g]!==v)D(s),Z(e,s[g],s[_]);else if(o!==b&&"function"==typeof h)try{h.call(s,c(E(e,o)),c(E(e,!1)))}catch(u){c(()=>{Z(e,!1,u)})()}else{e[g]=o;const c=e[_];if(e[_]=s,e[k]===k&&o===T&&(e[g]=e[y],e[_]=e[m]),o===b&&s instanceof Error){const e=t.currentTask&&t.currentTask.data&&t.currentTask.data.__creationTrace__;e&&r(s,w,{configurable:!0,enumerable:!1,writable:!0,value:e})}for(let t=0;t{try{const o=e[_],r=!!n&&k===n[k];r&&(n[m]=o,n[y]=s);const i=t.run(a,void 0,r&&a!==d&&a!==f?[]:[o]);Z(n,!0,i)}catch(o){Z(n,!1,o)}},n)}const O=function(){};class C{static toString(){return"function ZoneAwarePromise() { [native code] }"}static resolve(e){return Z(new this(null),T,e)}static reject(e){return Z(new this(null),b,e)}static race(e){let t,n,o=new this((e,o)=>{t=e,n=o});function r(e){t(e)}function s(e){n(e)}for(let a of e)p(a)||(a=this.resolve(a)),a.then(r,s);return o}static all(e){return C.allWithCallback(e)}static allSettled(e){return(this&&this.prototype instanceof C?this:C).allWithCallback(e,{thenCallback:e=>({status:"fulfilled",value:e}),errorCallback:e=>({status:"rejected",reason:e})})}static allWithCallback(e,t){let n,o,r=new this((e,t)=>{n=e,o=t}),s=2,a=0;const i=[];for(let l of e){p(l)||(l=this.resolve(l));const e=a;try{l.then(o=>{i[e]=t?t.thenCallback(o):o,s--,0===s&&n(i)},r=>{t?(i[e]=t.errorCallback(r),s--,0===s&&n(i)):o(r)})}catch(c){o(c)}s++,a++}return s-=2,0===s&&n(i),r}constructor(e){const t=this;if(!(t instanceof C))throw new Error("Must be an instanceof Promise.");t[g]=v,t[_]=[];try{e&&e(E(t,T),E(t,b))}catch(n){Z(t,!1,n)}}get[Symbol.toStringTag](){return"Promise"}get[Symbol.species](){return C}then(e,n){let o=this.constructor[Symbol.species];o&&"function"==typeof o||(o=this.constructor||C);const r=new o(O),s=t.current;return this[g]==v?this[_].push(s,r,e,n):P(this,s,r,e,n),r}catch(e){return this.then(null,e)}finally(e){let n=this.constructor[Symbol.species];n&&"function"==typeof n||(n=C);const o=new n(O);o[k]=k;const r=t.current;return this[g]==v?this[_].push(r,o,e,e):P(this,r,o,e,e),o}}C.resolve=C.resolve,C.reject=C.reject,C.race=C.race,C.all=C.all;const z=e[c]=e.Promise;e.Promise=C;const j=s("thenPatched");function I(e){const t=e.prototype,n=o(t,"then");if(n&&(!1===n.writable||!n.configurable))return;const r=t.then;t[l]=r,e.prototype.then=function(e,t){return new C((e,t)=>{r.call(this,e,t)}).then(e,t)},e[j]=!0}return n.patchThen=I,z&&(I(z),R(e,"fetch",e=>{return t=e,function(e,n){let o=t.apply(e,n);if(o instanceof C)return o;let r=o.constructor;return r[j]||I(r),o};var t})),Promise[t.__symbol__("uncaughtPromiseErrors")]=a,C}),Zone.__load_patch("toString",e=>{const t=Function.prototype.toString,n=k("OriginalDelegate"),o=k("Promise"),r=k("Error"),s=function(){if("function"==typeof this){const s=this[n];if(s)return"function"==typeof s?t.call(s):Object.prototype.toString.call(s);if(this===Promise){const n=e[o];if(n)return t.call(n)}if(this===Error){const n=e[r];if(n)return t.call(n)}}return t.call(this)};s[n]=t,Function.prototype.toString=s;const a=Object.prototype.toString;Object.prototype.toString=function(){return"function"==typeof Promise&&this instanceof Promise?"[object Promise]":a.call(this)}});let F=!1;if("undefined"!=typeof window)try{const e=Object.defineProperty({},"passive",{get:function(){F=!0}});window.addEventListener("test",e,e),window.removeEventListener("test",e,e)}catch(de){F=!1}const q={useG:!0},G={},B={},W=new RegExp("^"+d+"(\\w+)(true|false)$"),U=k("propagationStopped");function V(e,t){const n=(t?t(e):e)+f,o=(t?t(e):e)+p,r=d+n,s=d+o;G[e]={},G[e].false=r,G[e].true=s}function $(e,t,n){const o=n&&n.add||c,r=n&&n.rm||l,a=n&&n.listeners||"eventListeners",i=n&&n.rmAll||"removeAllListeners",u=k(o),h="."+o+":",g=function(e,t,n){if(e.isRemoved)return;const o=e.callback;"object"==typeof o&&o.handleEvent&&(e.callback=e=>o.handleEvent(e),e.originalDelegate=o),e.invoke(e,t,[n]);const s=e.options;s&&"object"==typeof s&&s.once&&t[r].call(t,n.type,e.originalDelegate?e.originalDelegate:e.callback,s)},_=function(t){if(!(t=t||e.event))return;const n=this||t.target||e,o=n[G[t.type].false];if(o)if(1===o.length)g(o[0],n,t);else{const e=o.slice();for(let o=0;ofunction(t,n){t[U]=!0,e&&e.apply(t,n)})}function Y(e,t,n,o,r){const s=Zone.__symbol__(o);if(t[s])return;const a=t[s]=t[o];t[o]=function(s,i,c){return i&&i.prototype&&r.forEach(function(t){const r=`${n}.${o}::`+t,s=i.prototype;if(s.hasOwnProperty(t)){const n=e.ObjectGetOwnPropertyDescriptor(s,t);n&&n.value?(n.value=e.wrapWithCurrentZone(n.value,r),e._redefineProperty(i.prototype,t,n)):s[t]&&(s[t]=e.wrapWithCurrentZone(s[t],r))}else s[t]&&(s[t]=e.wrapWithCurrentZone(s[t],r))}),a.call(t,s,i,c)},e.attachOriginToPatched(t[o],a)}const K=["absolutedeviceorientation","afterinput","afterprint","appinstalled","beforeinstallprompt","beforeprint","beforeunload","devicelight","devicemotion","deviceorientation","deviceorientationabsolute","deviceproximity","hashchange","languagechange","message","mozbeforepaint","offline","online","paint","pageshow","pagehide","popstate","rejectionhandled","storage","unhandledrejection","unload","userproximity","vrdisplayconnected","vrdisplaydisconnected","vrdisplaypresentchange"],Q=["encrypted","waitingforkey","msneedkey","mozinterruptbegin","mozinterruptend"],ee=["load"],te=["blur","error","focus","load","resize","scroll","messageerror"],ne=["bounce","finish","start"],oe=["loadstart","progress","abort","error","load","progress","timeout","loadend","readystatechange"],re=["upgradeneeded","complete","abort","success","error","blocked","versionchange","close"],se=["close","error","open","message"],ae=["error","message"],ie=["abort","animationcancel","animationend","animationiteration","auxclick","beforeinput","blur","cancel","canplay","canplaythrough","change","compositionstart","compositionupdate","compositionend","cuechange","click","close","contextmenu","curechange","dblclick","drag","dragend","dragenter","dragexit","dragleave","dragover","drop","durationchange","emptied","ended","error","focus","focusin","focusout","gotpointercapture","input","invalid","keydown","keypress","keyup","load","loadstart","loadeddata","loadedmetadata","lostpointercapture","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","mousewheel","orientationchange","pause","play","playing","pointercancel","pointerdown","pointerenter","pointerleave","pointerlockchange","mozpointerlockchange","webkitpointerlockerchange","pointerlockerror","mozpointerlockerror","webkitpointerlockerror","pointermove","pointout","pointerover","pointerup","progress","ratechange","reset","resize","scroll","seeked","seeking","select","selectionchange","selectstart","show","sort","stalled","submit","suspend","timeupdate","volumechange","touchcancel","touchmove","touchstart","touchend","transitioncancel","transitionend","waiting","wheel"].concat(["webglcontextrestored","webglcontextlost","webglcontextcreationerror"],["autocomplete","autocompleteerror"],["toggle"],["afterscriptexecute","beforescriptexecute","DOMContentLoaded","freeze","fullscreenchange","mozfullscreenchange","webkitfullscreenchange","msfullscreenchange","fullscreenerror","mozfullscreenerror","webkitfullscreenerror","msfullscreenerror","readystatechange","visibilitychange","resume"],K,["beforecopy","beforecut","beforepaste","copy","cut","paste","dragstart","loadend","animationstart","search","transitionrun","transitionstart","webkitanimationend","webkitanimationiteration","webkitanimationstart","webkittransitionend"],["activate","afterupdate","ariarequest","beforeactivate","beforedeactivate","beforeeditfocus","beforeupdate","cellchange","controlselect","dataavailable","datasetchanged","datasetcomplete","errorupdate","filterchange","layoutcomplete","losecapture","move","moveend","movestart","propertychange","resizeend","resizestart","rowenter","rowexit","rowsdelete","rowsinserted","command","compassneedscalibration","deactivate","help","mscontentzoom","msmanipulationstatechanged","msgesturechange","msgesturedoubletap","msgestureend","msgesturehold","msgesturestart","msgesturetap","msgotpointercapture","msinertiastart","mslostpointercapture","mspointercancel","mspointerdown","mspointerenter","mspointerhover","mspointerleave","mspointermove","mspointerout","mspointerover","mspointerup","pointerout","mssitemodejumplistitemremoved","msthumbnailclick","stop","storagecommit"]);function ce(e,t,n){if(!n||0===n.length)return t;const o=n.filter(t=>t.target===e);if(!o||0===o.length)return t;const r=o[0].ignoreProperties;return t.filter(e=>-1===r.indexOf(e))}function le(e,t,n,o){e&&z(e,ce(e,t,n),o)}function ue(e,t){if(Z&&!D)return;if(Zone[e.symbol("patchEvents")])return;const n="undefined"!=typeof WebSocket,o=t.__Zone_ignore_on_properties;if(S){const e=window,t=A()?[{target:e,ignoreProperties:["error"]}]:[];le(e,ie.concat(["messageerror"]),o?o.concat(t):o,s(e)),le(Document.prototype,ie,o),void 0!==e.SVGElement&&le(e.SVGElement.prototype,ie,o),le(Element.prototype,ie,o),le(HTMLElement.prototype,ie,o),le(HTMLMediaElement.prototype,Q,o),le(HTMLFrameSetElement.prototype,K.concat(te),o),le(HTMLBodyElement.prototype,K.concat(te),o),le(HTMLFrameElement.prototype,ee,o),le(HTMLIFrameElement.prototype,ee,o);const n=e.HTMLMarqueeElement;n&&le(n.prototype,ne,o);const r=e.Worker;r&&le(r.prototype,ae,o)}const r=t.XMLHttpRequest;r&&le(r.prototype,oe,o);const a=t.XMLHttpRequestEventTarget;a&&le(a&&a.prototype,oe,o),"undefined"!=typeof IDBIndex&&(le(IDBIndex.prototype,re,o),le(IDBRequest.prototype,re,o),le(IDBOpenDBRequest.prototype,re,o),le(IDBDatabase.prototype,re,o),le(IDBTransaction.prototype,re,o),le(IDBCursor.prototype,re,o)),n&&le(WebSocket.prototype,se,o)}Zone.__load_patch("util",(e,t,n)=>{n.patchOnProperties=z,n.patchMethod=R,n.bindArguments=b,n.patchMacroTask=M;const s=t.__symbol__("BLACK_LISTED_EVENTS"),u=t.__symbol__("UNPATCHED_EVENTS");e[u]&&(e[s]=e[u]),e[s]&&(t[s]=t[u]=e[s]),n.patchEventPrototype=J,n.patchEventTarget=$,n.isIEOrEdge=H,n.ObjectDefineProperty=r,n.ObjectGetOwnPropertyDescriptor=o,n.ObjectCreate=a,n.ArraySlice=i,n.patchClass=I,n.wrapWithCurrentZone=g,n.filterProperties=ce,n.attachOriginToPatched=N,n._redefineProperty=Object.defineProperty,n.patchCallbacks=Y,n.getGlobalObjects=()=>({globalSources:B,zoneSymbolEventNames:G,eventNames:ie,isBrowser:S,isMix:D,isNode:Z,TRUE_STR:p,FALSE_STR:f,ZONE_SYMBOL_PREFIX:d,ADD_EVENT_LISTENER_STR:c,REMOVE_EVENT_LISTENER_STR:l})});const he=k("zoneTask");function pe(e,t,n,o){let r=null,s=null;n+=o;const a={};function i(t){const n=t.data;return n.args[0]=function(){return t.invoke.apply(this,arguments)},n.handleId=r.apply(e,n.args),t}function c(t){return s.call(e,t.data.handleId)}r=R(e,t+=o,n=>function(r,s){if("function"==typeof s[0]){const e={isPeriodic:"Interval"===o,delay:"Timeout"===o||"Interval"===o?s[1]||0:void 0,args:s},n=s[0];s[0]=function(){try{return n.apply(this,arguments)}finally{e.isPeriodic||("number"==typeof e.handleId?delete a[e.handleId]:e.handleId&&(e.handleId[he]=null))}};const r=_(t,s[0],e,i,c);if(!r)return r;const l=r.data.handleId;return"number"==typeof l?a[l]=r:l&&(l[he]=r),l&&l.ref&&l.unref&&"function"==typeof l.ref&&"function"==typeof l.unref&&(r.ref=l.ref.bind(l),r.unref=l.unref.bind(l)),"number"==typeof l||l?l:r}return n.apply(e,s)}),s=R(e,n,t=>function(n,o){const r=o[0];let s;"number"==typeof r?s=a[r]:(s=r&&r[he],s||(s=r)),s&&"string"==typeof s.type?"notScheduled"!==s.state&&(s.cancelFn&&s.data.isPeriodic||0===s.runCount)&&("number"==typeof r?delete a[r]:r&&(r[he]=null),s.zone.cancelTask(s)):t.apply(e,o)})}function fe(e,t){if(Zone[t.symbol("patchEventTarget")])return;const{eventNames:n,zoneSymbolEventNames:o,TRUE_STR:r,FALSE_STR:s,ZONE_SYMBOL_PREFIX:a}=t.getGlobalObjects();for(let c=0;c{const t=e[Zone.__symbol__("legacyPatch")];t&&t()}),Zone.__load_patch("queueMicrotask",(e,t,n)=>{n.patchMethod(e,"queueMicrotask",e=>function(e,n){t.current.scheduleMicroTask("queueMicrotask",n[0])})}),Zone.__load_patch("timers",e=>{const t="set",n="clear";pe(e,t,n,"Timeout"),pe(e,t,n,"Interval"),pe(e,t,n,"Immediate")}),Zone.__load_patch("requestAnimationFrame",e=>{pe(e,"request","cancel","AnimationFrame"),pe(e,"mozRequest","mozCancel","AnimationFrame"),pe(e,"webkitRequest","webkitCancel","AnimationFrame")}),Zone.__load_patch("blocking",(e,t)=>{const n=["alert","prompt","confirm"];for(let o=0;ofunction(o,s){return t.current.run(n,e,s,r)})}),Zone.__load_patch("EventTarget",(e,t,n)=>{!function(e,t){t.patchEventPrototype(e,t)}(e,n),fe(e,n);const o=e.XMLHttpRequestEventTarget;o&&o.prototype&&n.patchEventTarget(e,[o.prototype])}),Zone.__load_patch("MutationObserver",(e,t,n)=>{I("MutationObserver"),I("WebKitMutationObserver")}),Zone.__load_patch("IntersectionObserver",(e,t,n)=>{I("IntersectionObserver")}),Zone.__load_patch("FileReader",(e,t,n)=>{I("FileReader")}),Zone.__load_patch("on_property",(e,t,n)=>{ue(n,e)}),Zone.__load_patch("customElements",(e,t,n)=>{!function(e,t){const{isBrowser:n,isMix:o}=t.getGlobalObjects();(n||o)&&e.customElements&&"customElements"in e&&t.patchCallbacks(t,e.customElements,"customElements","define",["connectedCallback","disconnectedCallback","adoptedCallback","attributeChangedCallback"])}(e,n)}),Zone.__load_patch("XHR",(e,t)=>{!function(e){const c=e.XMLHttpRequest;if(!c)return;const l=c.prototype;let p=l[u],f=l[h];if(!p){const t=e.XMLHttpRequestEventTarget;if(t){const e=t.prototype;p=e[u],f=e[h]}}const d="readystatechange",g="scheduled";function m(e){const o=e.data,a=o.target;a[s]=!1,a[i]=!1;const c=a[r];p||(p=a[u],f=a[h]),c&&f.call(a,d,c);const l=a[r]=()=>{if(a.readyState===a.DONE)if(!o.aborted&&a[s]&&e.state===g){const n=a[t.__symbol__("loadfalse")];if(0!==a.status&&n&&n.length>0){const r=e.invoke;e.invoke=function(){const n=a[t.__symbol__("loadfalse")];for(let t=0;tfunction(e,t){return e[o]=0==t[2],e[a]=t[1],T.apply(e,t)}),b=k("fetchTaskAborting"),E=k("fetchTaskScheduling"),w=R(l,"send",()=>function(e,n){if(!0===t.current[E])return w.apply(e,n);if(e[o])return w.apply(e,n);{const t={target:e,url:e[a],isPeriodic:!1,args:n,aborted:!1},o=_("XMLHttpRequest.send",y,t,m,v);e&&!0===e[i]&&!t.aborted&&o.state===g&&o.invoke()}}),Z=R(l,"abort",()=>function(e,o){const r=e[n];if(r&&"string"==typeof r.type){if(null==r.cancelFn||r.data&&r.data.aborted)return;r.zone.cancelTask(r)}else if(!0===t.current[b])return Z.apply(e,o)})}(e);const n=k("xhrTask"),o=k("xhrSync"),r=k("xhrListener"),s=k("xhrScheduled"),a=k("xhrURL"),i=k("xhrErrorBeforeScheduled")}),Zone.__load_patch("geolocation",e=>{e.navigator&&e.navigator.geolocation&&function(e,t){const n=e.constructor.name;for(let r=0;r{const t=function(){return e.apply(this,b(arguments,n+"."+s))};return N(t,e),t})(a)}}}(e.navigator.geolocation,["getCurrentPosition","watchPosition"])}),Zone.__load_patch("PromiseRejectionEvent",(e,t)=>{function n(t){return function(n){X(e,t).forEach(o=>{const r=e.PromiseRejectionEvent;if(r){const e=new r(t,{promise:n.promise,reason:n.rejection});o.invoke(e)}})}}e.PromiseRejectionEvent&&(t[k("unhandledPromiseRejectionHandler")]=n("unhandledrejection"),t[k("rejectionHandledHandler")]=n("rejectionhandled"))})}},[[1,0]]]); --------------------------------------------------------------------------------