{"id":18244739,"url":"https://github.com/devdevi/angular-9-store","last_synced_at":"2025-04-08T18:48:14.582Z","repository":{"id":38570297,"uuid":"255003496","full_name":"devdevi/angular-9-store","owner":"devdevi","description":null,"archived":false,"fork":false,"pushed_at":"2022-06-03T02:23:56.000Z","size":4159,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-14T14:53:33.871Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devdevi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-12T03:48:31.000Z","updated_at":"2020-05-29T23:31:44.000Z","dependencies_parsed_at":"2022-08-25T06:42:28.506Z","dependency_job_id":null,"html_url":"https://github.com/devdevi/angular-9-store","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devdevi%2Fangular-9-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devdevi%2Fangular-9-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devdevi%2Fangular-9-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devdevi%2Fangular-9-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devdevi","download_url":"https://codeload.github.com/devdevi/angular-9-store/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247909107,"owners_count":21016475,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T09:17:28.135Z","updated_at":"2025-04-08T18:48:14.553Z","avatar_url":"https://github.com/devdevi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Store\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.1.\n\n## Development server\n\nRun `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.\n\n## Code scaffolding\n\nRun `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.\n\n## Build\n\nRun `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.\n\n## Running unit tests\n\nRun `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Running end-to-end tests\n\nRun `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n\n\n### Construyendo una directiva propia\n``` ng g d highlight\nng g m admin --routing\n```\n\n\n### Introducción al NgModule\nModularize nuestra app por dominios, módulos especiales el modulo core y el modulo share\nLos módulos y rutas sirven para dividir y abstraer mejor por dominio la aplicación.\n\nLos componentes que hacen parte de una página en particular se pueden encapsular en un mismo módulo.\n\nLos módulos especiales son core y shared.\n\nCore: guarda todos los servicios y componentes que usaremos a lo largo de todos los otros módulos.\nShared: podemos almacenar componentes y servicios compartidos.\n\n### Implementación del Lazy Loading\nPreparar el proyecto para Lazy Loading\nÉsta técnica se encarga de fragmentar el archivo generado main.js para que cargue más rápido la aplicación, basada en la técnica “divide y vencerás”, cargando siempre el código JavaScript necesario para que la vista funcione de manera adecuada.\n\nCon ésto claro, un pre-requisito fundamental es modularizar la aplicación. Un módulo encapsula varios elementos de la aplicación (components, directivas, servicios, etc)\n\nModularizando home:\n\nCrear archivo home/home.module.ts\nng g module components/home\n\nCrear carpeta home/components\nCopiar y pegar los componentes que el módulo home va a utilizar\nEliminar el componente del array de declarations de otros módulos e importarlo al módulo creado\nCrear el routing para el módulo Home. En angular cada módulo debe tener un routing\ncd src/app/components/home\nng g module home-routing --flat --module=home\n\n### Esta clase es oro. La clave para separar los módulos es:\n\nCrear una carpeta que contendrá el módulo\nCrear un módulo que llame a todos los componentes que utilizará\nCrear un módulo para sus rutas\nCambiar la importación dentro del routing principal\nEliminar referencias o errores que surjan por el movimiento\n\n### Ambientes en Angular\nUn entorno de aplicación en Angular (environment) es información de configuración JSON que le dice al sistema de compilación qué archivos cambiar cuando usa ng build y ng serve.\n.\nLa recomendación es hacer ambientes dentro del directorio environments/environment.[nombre].ts, y para registrarlo necesitas modificar el archivo angular.json\n.\nPara agregar un nuevo ambiente al angular.json se necesitan duplicar el environment de build y de serve dentro de projects.\u003cproject-name\u003e.architect.build.configurations.nameOfNewEnvironment y de projects.\u003cproject-name\u003e.architect.serve.configurations.production y cambiar production por el nombre que quieras que reciba tu environment, como staging o local, etc.\n.\nRecuerda que es muy delicado este archivo y que lo tienes que hacer a conciencia, además de que tienes que colocar la ruta de tu archivo de environments en fileReplacements, porque lo que hace este archivo es reemplazar las ocurrencias de importación de src/environments/environment.ts por el archivo de ambiente que le indiques.\n\n\n```\n{\n  projects: {\n    nameOfProject: {\n      ...\n      architect: {\n        build: {\n          ...\n          production: {} \u003c-- Duplicar este objeto\n        },\n        serve: {\n          configurations: {\n            ...\n            production: {} \u003c-- Duplicar este objeto\n          }\n        }\n      }\n    }\n  }\n}\n\n```\n\n```\nng serve -c=stag\n\u003c!-- Productivo --\u003e\n\nng build -c=stag\n```\n\n### Observable es un patrón de diseño de software, donde básicamente tienes algo que observar (Observable) pueden ser eventos de un formulario, un llamada Htttp, etc, nosotros podemos suscribirnos a esos eventos. Otro componente importante es el que observa (Observer) este es el que se suscribe a los eventos y por medio de callbacks captura los eventos que emite el observable, por último tenemos el subject o sujeto que es el que hace que el observable lance los eventos para ser capturados.\nFlujo de datos continuo\n\n\n```shell\nng g c components/cart\n```\n\n- g = generate\n- c = component\n\n### Flags\n\n#### --inline-style\n\nEvita que se cree el archivo de estilos\n\n```shell\nng g c componente --inline-style\n```\n\n#### --inline-template\n\nEste evita que se cree el html\n\n```shell\nng g c componente --inline-template\n```\n\n## `ng lint`-\u003e\n\n```\nng lint\n```\n\nRevisa el código del proyecto para ver si se están cumpliendo las reglas definidas en el archivo tslint.json\n\n```\nng lint --format json\n```\n\nNos permite visualizar el resultado de la revisión con un formato json.\n\n```\nng lint --fix\n```\n\nCorrige automáticamente, dentro de lo posible, los errores encontrados.\n\n# [Directivas](https://angular.io/api/common#directives)\n\n## `ngIf`\n\nMuestra el componente sólo si cumple con la directiva\n\n```html\n\u003cdiv *ngIf=\"title==='david'\"\u003e \u003c!-- Sólo se mostrará si la condición es verdadera --\u003e\n  Súper div\n\u003c/div\u003e\n```\n\n## `ng-model`\n\nPermite hacer data binding, osea conectar entre un dato y un componente\n\n```html\n\u003cinput type=\"text\" [(ngModel)]=\"title\"\u003e \u003c!-- Needs to import FormsModule in app.module.ts --\u003e\n```\n\n\n\nEn proyectos reales puedes que te encuentres con dos tipos de NgModel\n\n1. [(ngModel)]=“nombre”\n2. [ngModel]=“apellido”\n\nEl primero hace un enlace de doble sentido, es decir, si se actualiza la vista se actualiza el valor y si se actualiza el valor se actualiza la vista.\n\nEl segundo hace un enlace de un sólo sentido, este sentido va desde el modelo a la vista, pero la vista NO puede actualizar al modelo. Pueden copiar y pegar este código para comprobarlo.\n\n# String interpolation\n\nLa interpolación es la forma de mostrar datos del **Componente** al **DOM** (esa representación que hace el browser del **HTML** con forma de objetos). Su notación es en forma de doble brackets `{{}}` () y lo que está dentro de esos brackets es lo que se quiere mostrar en pantalla «procesado».\n\nLos templates de Angular utilizan html como lenguaje de maquetación donde se puede ejecutar interpolación de strings mediante una implementación de moustache donde dentro de los corchetes puedes hacer una sentencia que se resolverá como un string para ser renderizado en el DOM.\n\nNuestros templates tienen acceso a las variables exportadas en el arc`.ts` con el mismo nombre, mismas que podemos renderizar mediante los string interpolation, por ejemplo:\n\n```html\n\u003ch1\u003e{{ title }}\u003c/h1\u003e \u003c!-- Renderiza el título exportado en el archiv ts --\u003e\n\u003cp\u003e\n  Las suma de 2 + 2 = {{ 2 + 2 }} \u003c!-- 4 --\u003e\n\u003c/p\u003e\n```\n\nAngular divide la lógica de la vista, pero puedes hacer uso de los elementos de uno o del otro en las 2 partes.\n\n## `{{ template-expression }}`\n\nUn template expresion es la expresión que se va a evaluar para renderizarse en el DOM.\n\nLos tipos de **Template Expresion** válidos pueden ser:\n\n- **{{ `1 + 1` }}**: la cual devuelve 2\n- **{{ `miVariable` }}**: donde miVariable es una variable definida en el **Component**\n- **{{ `miMetodo()` }}** : donde miMetodo() es un método definido en el **Component**\n\nTambién se le puede asignar a un atributo **HTML** (que espere un string) el valor de una **Template Expresion**, por ejemplo\n\n`\u003ch1 innerText = {{pageTitle}}\u003e\u003ch1\u003e`  ← se asigna un valor “ya procesado” a un **Tag HTML**\n\n# Directivas Propias\n\nPara crear una directiva\n\n```typescript\nng generate \u003cdirective\u003e\nng g \u003cdirective\u003e\n```\n\nLas directivas tienen un selector que es como su identificador el cual se debe colocar en las etiquetas como atributos.\n\nRecuerda que las directivas modifican dinamicamente los elementos desde el DOM, esto no es buena practica aplicarlo para todo ya que existen alternativas más usables como el data-binding\n\n## Ejemplo:\n\n**selector = ‘[appTabRequired]’**\n\nEn el constructor tendremos que hacer la inyeccion de dependencia **ElementRef**\n\n### constructor\n\n```typescript\nconstructor( element: ElementRef){\n   element.nativeElement.style.color = 'red';\n}\n```\n\n### hightlight.directive.ts\n\n```typescript\nimport { Directive, ElementRef } from '@angular/core';\n\n@Directive({\n  selector: '[appHighlight]'\n})\nexport class HighlightDirective {\n  constructor(\n    element: ElementRef\n  ) {\n    element.nativeElement.style.backgroundColor = 'blue';\n  }\n}\n\n```\n\n### Implementación en el template:\n\n```html\n\u003cdiv appHighlight\u003e\n  Contenido\n\u003c/div\u003e\n```\n\n\n\n# COMPONENTES EN ANGULAR - Sintaxis General\n\nEs muy bueno saber como construir un componente de manera manual, pero existe un comando para generar nuevos componentes de forma automática.\n\n```bash\nng g c nombredelcomponente\n```\n\nNomenclatura : **name.component.ts**\n\n## `Decoradores`:\n\nLe dan un contexto a los artefactos de angular. Y le asigna el tipo de rol que cumplirá.\n\nUn decorador angular es una clase especial de declaración que puede acoplarse a una clase, método, propiedad o parámetro. Los decoradores se declaran de la siguiente manera `@expression`. Gracias al parámetro `@` podemos reconocer fácilmente que estamos hablando de un decorador.\n\nGeneralmente usamos los decoradores para extender servicios de terceros, de esta manera evitamos modificar el código original del módulo y en tiempo de ejecución agregamos el funcionamiento que necesitamos.\n\n```javascript\nimport { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'selector-name',\n  templateUrl: './product.component.html'\n})\n\nexport class ProductComponent {\n  constructor() { }\n}\n```\n\n## `selector:`\n\nSe refiere al selector con el que vas a llamar a tu componente desde el html  (`\u003cselector-name /\u003e`)\n\n## `templateURL`\n\nEl templateURL: es el archivo html.\n\n## `class`:\n\nPara que la clase sea utilizada por cualquiera se debe hacer \"publica\"\n\n`export class ProductComponent`\n\nAdemás se debe importar el componente en el archivo `app.module.ts`,\n\n```javascript\nimport { Component } from 'component-route'\n...\n\n@NgModule({\n  declarations: [\n    ...\n    Component\n  ],\n  ...\n})\nexport class AppModule { }\n\n```\n\n# Uso de Inputs y Outputs\n\nUn componente sólo debe de tener una sóla responsabilidad (principio SOLID)\n\nLo que seria props en React\n\nLa [documentación](https://angular.io/guide/component-interaction#parent-listens-for-child-event) de Angular respecto a la comunicación entre componentes.\n\n[Artículo](https://samueleresca.net/2016/08/solid-principles-using-typescript/) que explica la aplicabilidad de los principios SOLID en Angular.\n\n## `Input`\n\nPara comunicar de un componente padre a un componente hijo usamos **Input**\n\n```typescript\nexport class ProductComponent {\n  @Input() product: Product; // Equivalente a prop, dónde le vamos a pasar la data al componente\n}\n```\n\nPara pasar argumentos, desde el template padre podemos utilizar los corchetes cuadrados con el Input para pasar el argumento\n\n```html\n\u003capp-product [product]=\"products[0]\"\u003e\u003c/app-product\u003e\n```\n\n```html\n\u003cdiv *ngFor=\"let product of products\"\u003e\n  \u003capp-product [product]=\"product\"\u003e\u003c/app-product\u003e\n\u003c/div\u003e\n```\n\n## `Output`\n\nPara comunicar de un componente hijo a un componente padre usamos **Output**.\n\nLos `Output` son eventos que podemos cachar desde nuestro componente hijo por parte del padre.\n\nPara declararlos en nuestro componente tenemos que usar el decorador `@Output` sobre un `EventEmitter`\n\n```typescript\nexport class ProductComponent {\n  @Output() clickAddToCart = new EventEmitter\u003cany\u003e(); // (clickAddToCart)= eventHandler($event):function\n  ...\n}\n```\n\nLos `EventEmmiter`'s pueden emitir un evento con un argumento que será recibido por el padre.\n\n```typescript\nexport class ProductComponent {\n  @Output() clickAddToCart = new EventEmitter\u003cany\u003e(); // (clickAddToCart)= eventHandler($event):function\n  addToCart(){\n    this.clickAddToCart.emit(this.product.id)\n  }\n}\n```\n\nPara hacer uso del output podemos llamar el evento desde paréntesis y asignarle un evento `(clickAddToCart)=\"handler($event)\"`:\n\n```typescript\n// Componente padre\nexport class AppComponent {\n ...\n  handleProductAddToCart(id: number) {\n    console.log('product -\u003e id', id);\n  }\n}\n\n// Template del componente padre\n\u003capp-product\n  (clickAddToCart)=\"handleProductAddToCart($event)\"\n\u003e\u003c/app-product\u003e\n\n```\n\nEl event es recibido desde el `emit` del `EventEmmiter` :\n\n`this.clickAddToCart.emit(this.product.id)`\n\n## `Observables`\n\n### Referencias:\n\n- https://desarrolloweb.com/articulos/introduccion-teorica-observables-angular.html\n- https://platzi.com/clases/1071-angular2/6433-que-es-un-observable/\n\nObservable es un patrón de diseño de software, donde básicamente tienes algo que observar (Observable) pueden ser eventos de un formulario, un llamada Htttp, etc, nosotros podemos suscribirnos a esos eventos. Otro componente importante es el que observa (Observer) este es el que se suscribe a los eventos y por medio de callbacks captura los eventos que emite el observable, por último tenemos el subject o sujeto que es el que hace que el observable lance los eventos para ser capturados.\n\nUn Observer crea un espacio de ejecución independiente para cada suscriptor que este tenga.\n\n# Ciclo de vida del componente\n\n`ngOnChanges` y `ngDoCheck` tienen un error de colisión, ya que los dos pueden cumplir la tarea de escuchar por cambios del componente. El primero es la forma nativa de Angular, el segundo es una forma customizada para ello.\n\n `ngOnDestroy` nos ayudará remover las suscripciones a datos que inicializamos en algún momento, así podemos evitar bucles y fugas de memoria en la aplicación, es decir, limpiamos procesos de memoria siguiendo buenas prácticas.\n\n![](https://static.platzi.com/media/user_upload/Ciclo-97b9ac82-5217-4dd1-ae4d-3f30c08cfa9b.jpg)\n\n# [Pipes](https://angular.io/api/common/DatePipe) | tuberías o transformaciones\n\nLos `pipes` en Angular son transformaciones que se le puede hacer a un dato dentro de una **template-expression** sirve para formatear data como se desee.\n\nLos pipes pueden ser anidados, por lo que puede ser bastante poderoso.\n\nLa sintaxis es `{{ variableName | pipeName:argumentos }}`\n\nNosotros podemos crear nuestros pipes, pero Angular por defecto provee muchos pipes que podemos implementar sin muchas complicaciones, mismos que pueden ser configurables en el `app.module.ts` éstos son los comunes:\n\n- [ AsyncPipe](https://angular.io/api/common/AsyncPipe)\n- [ CurrencyPipe](https://angular.io/api/common/CurrencyPipe)\n- [ DatePipe](https://angular.io/api/common/DatePipe)\n- [ DecimalPipe](https://angular.io/api/common/DecimalPipe)\n- [ I18nPluralPipe](https://angular.io/api/common/I18nPluralPipe)\n- [ I18nSelectPipe](https://angular.io/api/common/I18nSelectPipe)\n- [ JsonPipe](https://angular.io/api/common/JsonPipe)\n- [ KeyValuePipe](https://angular.io/api/common/KeyValuePipe)\n- [ LowerCasePipe](https://angular.io/api/common/LowerCasePipe)\n- [ PercentPipe](https://angular.io/api/common/PercentPipe)\n- [ SlicePipe](https://angular.io/api/common/SlicePipe)\n- [ TitleCasePipe](https://angular.io/api/common/TitleCasePipe)\n- [ UpperCasePipe](https://angular.io/api/common/UpperCasePipe)\n\n[Pueden ver unos ejemplos acá](https://bit.ly/2oRRj0Z)\n\nPara agregar localismos a nuestros pipes (en este caso mexicanos) tendríamos que agregar el idioma a un `provider` dentro de `app.module.ts` de la siguiente forma:\n\n```typescript\n...\nimport { LOCALE_ID } from '@angular/core';\nimport localeEs from '@angular/common/locales/es';\nimport { registerLocaleData } from '@angular/common';\n\nregisterLocaleData(localeEs);\n...\n\n@NgModule({\n ...\n providers: [ { provide: LOCALE_ID, useValue: 'es-mx' } ],\n ...\n})\nexport class AppModule { }\n```\n\n## Pipes custom\n\nLos pipes en angular tienen muy buen rendimiento por lo que se recomiendan envés de las funciones para estos casos\n\nLos **pipes** nos sirven para transformar datos.\n\nUn dato puede ingresar y puede ser convertido segun el pipe usado\n\nRecuerda que si quieres generar tus propios pipes puedes usar\n\n```bash\n$ ng generate pipe \u003cname\u003e\n$ ng g pipe \u003cname\u003e\n```\n\n### Ejemplo de pipe custom\n\n```typescript\nimport { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n  name: 'exponential'\n})\nexport class ExponentialPipe implements PipeTransform {\n  transform(value: number, exp:number=2): number {\n    return Math.pow(value, exp);\n  }\n}\n```\n\n# ngModule\n\nLos módulos en angular sirven para resumir o adjuntar varios artefactos de Angular como servicios, componentes y directivas, dividiendo y abstrayendo el dominio de la aplicación.\n\nDe esta manera\n\nLos componentes que hacen parte de una página en particular se pueden encapsular en un mismo módulo.\n\nLos módulos especiales son core y shared.\n\n- **core**: Guarda toda la funcionalidad de la aplicación que va a ser compartida, es decir que genera una sóla referencia de la funcionalidad, siguiendo el principio Singleton de SOLID, facilitando así el traslado de funcionalidad entre aplicaciones. guarda todos los servicios y componentes que usaremos a lo largo de todos los otros módulos. Este sera usado en **todos ** los otros componentes y/o modulos respetando los principios SOLID (SINGLETON)\n- **shared**: Encapsula los componentes y servicios compartidos para la aplicación. podemos almacenar componentes y servicios compartidos. En este podemos tener componentes servicios y/o compartidos.\n\n## RUTAS EN ANGULAR\n\nEn el archivo **app-routing-module.ts** se encuentra un objeto **Route** el cual sirve para incrustar las rutas del proyecto.\n\nLa sintaxis dentro del router (`app-routing-module.ts`):\n\n```json\nimport { componentName } from './url/to/componentName.component';\n\nconst routes: Routes = [\n  {\n    path = ‘routeName’,\n    component = componentName\n  },\n]\n\n```\n\nDonde:\n\n- `path` = ruta relativa al home ('/') de nuestra app\n- `component` = componente importado desde `componentName.component.ts`\n\nLa forma de implementar el **router** en un **`template.html`** es con el componente `router-outlet`:\n\n```html\n\u003c!-- app.component.html --\u003e\n\n\u003crouter-outlet\u003e\u003c/router-outlet\u003e\n```\n\nDonde el `router-outlet` se reemplazará por el contenido del componente según la URL en la que estés\n\n### Páginas no encontradas (not-found)\n\nPara definir una página no encontrada podemos utilizar la ruta `'**'` que simboliza cualquier ruta diferente a las anteriormente definidas, el componente también deberá de ser el objeto del componente importado.\n\n```js\n  {\n    path: '**',\n    component: NotFoundComponent\n  }\n```\n\n\u003e Nota: El orden de las rutas **es importante**, si algo matchea una ruta, no se segirá a la siguiente, por lo que el not-found, debería de ser la última ruta, siempre\n\n### Redirecciones\n\nPara las redirecciones tenemos que usar las propiedades `redirectTo:'route'` y `pathMatch:'full'`\n\n```typescript\n  {\n    path: 'from',\n    redirectTo: 'to',\n    pathMatch: 'full'\n  },\n```\n\nDonde:\n\n- `path`: Página actual\n- `redirectTo`: página a la que se redireccionará\n- `pathMatch`: tipo de match, en el caso de 'full' será con una relación exacta\n\n### Redirecciones sin recargar `routerLink`\n\nPara poder movernos entre rutas sin recargar nuestra página (tipo single page application) debemos agregar a nuestras anclas '`\u003ca\u003e`'  la directiva **`routerLink`** envés del atributo **`href`** para que Angular determine que no haga una recarga de la página.\n\n```html\n\u003cdiv\u003e\n     \u003ca routerLink=\"/home\"\u003eHome\u003c/a\u003e \u003c!-- Antes \u003ca href=\"/home\"\u003eHome\u003c/a\u003e --\u003e\n\u003c/div\u003e\n```\n\n### Ancla activa `routerLinkActive`\n\nPuedes definir una clase para cuando una ruta matchee completamente al agregar la directiva `routerLinkActive`, misma que agregará una clase al elemento que contenga un `routerLink`, de esta manera en los estilos podrás acceder al elemento seleccionado.\n\nLa recomendación es llamar \"`active`\" al routerLinkActive (`routerLinkActive=\"active\"\u003e`), de esta manera podrás acceder desde el css mediante la clase `.active`\n\n**html**\n\n```html\n\u003cnav\u003e\n    \u003ca routerLink=\"/home\" routerLinkActive=\"active\"\u003eHome\u003c/a\u003e\n    \u003ca routerLink=\"/products\" routerLinkActive=\"active\"\u003eProducts\u003c/a\u003e\n    \u003ca routerLink=\"/contact\" routerLinkActive=\"active\"\u003eContact\u003c/a\u003e\n\u003c/nav\u003e\n```\n\n**scss**\n\n```css\nnav a {\n  padding: 5px;\n  text-decoration: none;\n  \u0026.active {\n    background-color: papayawhip;\n  }\n}\n```\n\nAsí se vería un `app-routing.module.ts` completo:\n\n```typescript\n... // importaciones\nconst routes: Routes = [\n  {\n    path: 'home',\n    redirectTo: '',\n    pathMatch: 'full'\n  },\n  {\n    path: '',\n    component: HomeComponent\n  },\n  {\n    path: '**',\n    component: NotFoundComponent\n  },\n];\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  exports: [RouterModule]\n})\nexport class AppRoutingModule { }\n\n```\n\n### Vistas Anidadas\n\nA veces existen componentes que se utilizan en varios otros componentes, para esto existe la técnica de vistas anidadas, la cual consiste en crear un componente que albergue los elementos que se repiten y los otros componentes que los utilizan serán rutas hijas del componente creado anteriormente.\n\nPrimero creamos el componente que almacena los elementos con el comando ‘ng g c nombreComponente’\n\nLuego en los archivos del componente se almacenan los elementos que se utilizaran repetitivamente en otros componentes. En el archivo html se utiliza la etiqueta router-oulet para renderizar los componentes que se quieren cargar, y los elementos repetitivos se especifican.\n\n```html\n\u003capp-header\u003e\u003c/app-header\u003e\n\u003crouter-outlet\u003e\u003c/router-outlet\u003e\n\u003capp-footer\u003e\u003c/app-footer\u003e\n```\n\nEn el archivo routing se incorpora el componente creado anteriormente en la variable de routes, pero esta vez todos los componentes que se basen en este deberán estar anidadas. Para anidarlos el objeto del componente creado tendrá que tener una nueva característica ‘children’, el cual tendrá los ‘path’ y ‘component’ de las rutas que se basen en la anterior.\n\n```typescript\nconstroutes: Routes = [\n    {\n      path: '',\n      component: LayoutComponent,\n      children: [\n        {\n          path: '',\n          redirectTo: '/home',\n          pathMatch: 'full',\n        },\n        {\n          path: 'home',\n          component: HomeComponent\n        },\n        ...\n      ]\n    },\n    {\n      path: 'demo',\n      component: DemoComponent\n    },\n    {\n      path: '**',\n      component: PageNotFoundComponent\n    }\n  ];\n```\n\n\n\n# Servicios\n\nLos servicios proveen datos esencialmente. La forma de crear un servicio es en la terminal con los comandos ‘ng g s nombreServicio’.\nPor lo general tenemos 2 métodos esenciales en los servicios, uno para obtener todos los objetos guardados en una variable, y otro para obtener 1 objeto especifico.\n\n```typescript\nexport class someService {\n\n  store = [\n    {\n      id: '1',\n      title: 'title',\n      price: 10,\n    },\n    {\n      id: '2',\n      title: 'title',\n      price: 20,\n    }\n  ];\n\n  constructor() { }\n\n  getAllStored() {\n    returnthis.store;\n  }\n\n  getStored(id: string) {\n    returnthis.store.find(item =\u003e id === item.id);\n  }\n}\n```\n\n- El método getAllStored() devuelve todos los objetos almacenados en la variable.\n- El método getStored() devuelve 1 objeto especifico almacenado en la variable, en este caso se utiliza la variable id para buscar este objeto.\n\n**Componente para objetos**\nA veces es necesario crear componentes para desplegar la información de un solo objeto que provee un servicio. Para eso creamos un componente en la terminal con el comando ‘ng g c nombreComponente’\n\nLuego de esto debemos asignarle una ruta en el archivo de routing, pero en esta ocasión tendrá un parámetro dinámico que se enviará.\n\n```typescript\nconst routes: Routes = [\n    {\n      path: 'home',\n      component: HomeComponent\n    },\n    {\n      path: 'product',\n      component: ProductComponent\n    }\n    {\n      path: 'product/:id',\n      component: ProductDetailComponent\n    }\n\n];\n```\n\nEn el componente creado debemos realizar 2 importaciones de dependencias, estos son ‘ActivatedRoute’ y ‘Params’ de ‘@angular/router’. *Nota: no olvidar que las inyecciones de dependencia deben ingresarse como parámetro en el constructor.*\n\n```typescript\nimport { Component, OnInit } from '@angular/core';\nimport { ActivatedRoute, Params } from '@angular/router';\n\n@Component({\n  selector: 'app-product-detail',\n  templateUrl: './product-detail.component.html',\n  styleUrls: ['./product-detail.component.scss']\n})\nexport class ProductDetailComponent implements OnInit {\n\n  constructor(\n    private route: ActivatedRoute\n  ) { }\n\n  ngOnInit() {};\n\n}\n```\n\nDesde el ngOnInit() es la forma adecuada de recibir el parámetro definido anteriormente en la ruta, y se suscribe a el por si existen cambios, esto para ejecutar los cambios en la pagina por si cambia la ruta. La variable definida en la suscripción es de tipo Params que fue importado anteriormente.\n\n```typescript\nngOnInit() {\n    this.route.params.subscribe((params: Params) =\u003e {\n      const id = params.id;\n      console.log(id);\n    });\n  }\n```\n\nEn el método anterior capturamos el valor de id en params. *Es importante aclarar que params es un json.*\n\nAhora para consultar los objetos de un servicio debemos importar el servicio en sí. Con ello tendremos acceso a sus datos y métodos. *Los servicios son inyecciones de dependencia, por lo que hay que ingresarlos en el constructor.*\n\n```typescript\nimport { ProductsService } from'./../products.service';\nconstructor(\n        private route: ActivatedRoute,\n        private productsService: ProductsService\n){ }\n```\n\nEl servicio importado en este caso tiene un método que devuelve un objeto especifico en formato json que se busca a través de su id, por ello se solicita una variable de entrada que se utiliza para buscar dicho objeto. En el siguiente caso se guarda el objeto en una variable y se imprime por consola.\n\n```typescript\nngOnInit() {\n    this.route.params.subscribe((params: Params) =\u003e {\n      const id = params.id;\n      const product = this.productsService.getProduct(id);\n      console.log(product);\n    });\n  }\n```\n\n# **Modularizacion**\n\nUn modulo encapsula varios elementos de una aplicación. Por lo general se modulariza cada vista de nuestra aplicación. Para crear un modulo se utiliza el comando ‘ng g m nombreModulo’\n\nEs buena practica crear un modulo por vista, y dentro este una carpeta ‘components’ con los componentes que utilizara.\n\nEn los módulos existe un archivo ‘nombreModulo.module.ts’ el cual tendrá que importar los componentes que utilizara. En el ‘@ngModule’ se debe declarar los componentes que utilizara, y exportar los que se utilizaran en otros módulos.\n\n```typescript\nimport { NgModule } from '@angular/core';\n\nimport { BannerComponent } from '../components/banner/banner.component';\nimport { HomeComponent } from'./home.component';\n\n@NgModule({\n  declarations: [\n    BannerComponent,\n    HomeComponent\n  ],\n})\n\nexport class HomeModule {\n\n}\n```\n\nTambién los módulos tienen un archivo routing ‘nombreModulo-routing.module.ts’ en el cual se deben definir las rutas del modulo.\n\n```typescript\nimport { NgModule } from '@angular/core';\nimport { Routes, RouterModule } from '@angular/router';\n\nconstroutes: Routes = [];\n\n@NgModule({\n  imports: [\n    RouterModule.forChild(routes),\n  ],\n  exports: [\n    RouterModule\n  ]\n})\nexport class HomeRoutingModule {}\n```\n\nLuego de terminar con el archivo routing, este debe importarse al archivo ‘nombreModulo.module.ts’ para ser utilizado.\n\n```typescript\nimport { NgModule } from'@angular/core';\n\nimport { BannerComponent } from'./components/banner/banner.component';\nimport { HomeComponent } from'./home.component';\n\nimport { HomeRoutingModule } from'./home-routing.module';\n\n@NgModule({\n  declarations: [\n    BannerComponent,\n    HomeComponent\n  ],\n  imports: [\n    HomeRoutingModule\n  ]\n})\nexportclassHomeModule {\n\n}\n```\n\n## Lazy\n\nEs una técnica que ayuda a reducir el peso de las aplicaciones, de esta forma carga mas rápido el proyecto. La carga inicial de una pagina no debería ser Lazy ya que necesitamos que se cargue de una, como por ejemplo el Home.\n\nLa forma en que funciona es que el navegador realiza un request del html, el cual contiene las instrucciones de carga (archivos css, js e imágenes) y cuando identifica los archivos que necesita para cargar el modulo, realiza otro request para pedir dichos archivos. Para aplicar esta técnica es necesario modularizar la aplicación.\n\nCuando ya esta modularizado, hay que definir una ruta inicial en el archivo routing del modulo.\n\n```typescript\nimport { HomeComponent } from './components/home/home.component';\n\nconstroutes: Routes = [\n  {\n    path: '',\n    component: HomeComponent\n  }\n];\n```\n\nAhora en el app-routing cargamos la ruta del modulo con **loadChildren**, de esta forma se carga dinámicamente. De esta forma resolvemos todo un modulo (no un componente únicamente).\n\n```typescript\nconstroutes: Routes = [\n    {\n      path: '',\n      component: LayoutComponent,\n      children: [\n        {\n          path: '',\n          redirectTo: '/home',\n          pathMatch: 'full',\n        },\n        {\n          path: 'home',\n          loadChildren: () =\u003e import('./home/home.module').then(m =\u003e m.HomeModule)\n        }\n      ]\n    },\n    {\n      path: '**',\n      component: PageNotFoundComponent\n    }\n  ];\n```\n\nAhora tenemos que hacer que la aplicación realice una precarga de los otros módulos de las otras vistas cuando la vista que estamos consultando ya termine. Para realizarlo en el archivo ‘app-routing’ debemos cambiar de estrategia de carga, precargando los archivos con **‘PreloadAllModules’**. *No olvidar importar ‘PreloadAllModules’*\n\n```typescript\nimport { Routes, RouterModule, PreloadAllModules } from '@angular/router';\n\n  @NgModule({\n    imports: [RouterModule.forRoot(routes, {\n      preloadingStrategy: PreloadAllModules\n    })],\n    exports: [RouterModule]\n  })\n```\n\n# [Creando vistas con Angular schematic](https://material.angular.io/guide/schematics)\n\n*Schematics* es una forma de crear archivos o reglas desde el CLI (command line interfaces), material ya tiene incluídos algunos schematics muy útiles para poder crear componentes de uso regular.\n\nPara poder crear un schematic tienes que tener instalado `'angular/cdk'`, mismo que viene por defecto al instalar Angular desde el CLI, pero que se tiene que instalar si no llegasen a funcionar los comandos.\n\nLos schematics generan código, así que [busca en la documentación que quieres crear](https://material.angular.io/guide/schematics) y pégalo en la línea de comandos, por ejemplo:\n\n```\nng generate @angular/material:dashboard admin/components/dashboard\n\nng generate @angular/material:table admin/components/list-products\n\nng generate @angular/material:navigation admin/components/nav\n\nng generate @angular/material:address-form admin/components/product-form\n```\n\n# [`HtttpClient`](https://angular.io/guide/http)\n\nLa mayoría de las aplicaciones front-end se comunican con los servicios de back-end a través del protocolo HTTP. Los navegadores modernos admiten dos API diferentes para realizar solicitudes HTTP: la interfaz XMLHttpRequest y la API fetch(), pero Angular implementa su propia interfaz basada en XMLHttpRequest para facilitar el fetching de datos, api expuesta por los navegadores.\n\n`HttpClient` viene desde `@angular/common/http` y ofrece una interfaz API HTTP de cliente simplificada para aplicaciones Angular.\n\nLos beneficios adicionales de **HttpClient** incluyen:\n\n- Suite de **pruebas** simplificadas\n- Requests y responses **tipados**\n- **Intercepción** de requests y responses\n- **Observables**\n- Manejo de **errores** optimizado (mediante streams)\n\n.\n\nPara trabajar con HttpClient tenemos que crear un objeto de tipo HttpClient:\n\n```typescript\nimport { HttpClient } from '@angular/common/http';\nexport class ProductsService {\n  constructor( private http: HttpClient ) {}\n}\n```\n\nHttpClient provee métodos http basados en los verbos de protocolos http, por lo tanto podemos facilitar una capa de servicios que implemente los métodos específicos de cada acción http:\n\n```typescript\nexport class ProductsService {\n  ...\n  getAllProducts(): Observable\u003cProduct[]\u003e {\n    return this.http.get\u003cProduct[]\u003e(`${environment.url_api}/products`);\n  }\n  ...\n}\n```\n\nAlgunos de los métodos que podríamos utilizar son:\n\n- `http.get`\n- `http.post`\n- `http.put`\n- `http.patch`\n- `http.put`\n\nPor lo tanto así se vería una capa de servicios en Angular basados en `HttpClient`\n\n```typescript\n@Injectable({ providedIn: 'root' })\nexport class ProductsService {\n  constructor( private http: HttpClient ) {}\n  getAllProducts(): Observable\u003cProduct[]\u003e {\n    return this.http.get\u003cProduct[]\u003e(`${environment.url_api}/products`);\n  }\n  getProduct(id: string): Observable\u003cProduct\u003e {\n    return this.http.get\u003cProduct\u003e(`${environment.url_api}/products/${id}`);\n  }\n  createProduct(product: Product): any {\n    return this.http.post(`${environment.url_api}/products`, product);\n  }\n  updateProduct(id: string, changes: Partial\u003cProduct\u003e): any {\n    return this.http.put(`${environment.url_api}/products/${id}`, changes);\n  }\n  deleteProduct(id: string): any {\n    return this.http.delete(`${environment.url_api}/products/${id}`);\n  }\n}\n```\n\n# Ambientes en Angular\n\nUn entorno de aplicación en Angular (environment) es información de configuración JSON que le dice al sistema de compilación qué archivos cambiar cuando usa ng build y ng serve.\n\nLa recomendación es hacer ambientes dentro del directorio `environments/environment.[nombre].ts`, y para registrarlo necesitas modificar el archivo `angular.json`\n\nPara agregar un nuevo ambiente al `angular.json` se necesitan duplicar el environment de **`build`** y de **`serve`** dentro de **projects.\u003cproject-name\u003e.architect.build.configurations.nameOfNewEnvironment** y de **projects.\u003cproject-name\u003e.architect.serve.configurations.production** y cambiar production por el nombre que quieras que reciba tu environment, como staging o local, etc.\n\nRecuerda que es muy delicado este archivo y que lo tienes que hacer a conciencia, además de que tienes que colocar la ruta de tu archivo de environments en `fileReplacements`, porque lo que hace este archivo es reemplazar las ocurrencias de importación de `src/environments/environment.ts` por el archivo de ambiente que le indiques.\n\n```json\n{\n  projects: {\n    nameOfProject: {\n      ...\n      architect: {\n        build: {\n          ...\n          production: {} \u003c-- Duplicar este objeto\n        },\n        serve: {\n          configurations: {\n            ...\n            production: {} \u003c-- Duplicar este objeto\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n# Formularios Reactivos\n\nLos formularios reactivos ayudan a manejar entradas de formulario cuyos valores cambian con un enfoque explícito e inmutable para administrar el estado de un formulario en un momento dado.\n\nLos formularios reactivos difieren de los [formularios basadas en plantillas](https://angular.io/guide/forms) en los siguientes puntos.\n\n- Las formas reactivas son predecibles al ser síncronas con el modelo de datos\n- Son inmutables, por lo tanto cada cambio en el estado del formulario devuelve un nuevo estado,\n- seguimiento de cambios a través de streams observables.\n\n- Proporcionan una ruta directa a las pruebas porque tiene la seguridad de que sus datos son consistentes y predecibles cuando se solicitan.\n- Cualquier consumidor de los streams tiene acceso para manipular estos datos de manera segura\n- Se construyen alrededor de [observable](https://angular.io/guide/glossary#observable) streams\n\nAdemás proveen métodos más sencillos para:\n\n- La validación de datos\n- Realización de pruebas unitarias:  porque tienes la seguridad de que sus datos son consistentes y predecibles al momento de solicitarlos.\n- Tener lógicas más complejas\n\n## `FormControl`\n\nUn input de tipo FormControl permite la anidación de validadores (ValidatorFn) con los que podemos de manera sencilla validar la fuente de datos.\n\n```typescript\nFormControl(\n  formState?: any,\n  validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions,\n  asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]\n): FormControl\n```\n\nSe definen detro de una variable de tipo `FormControl()` y se pueden llamar en el template:\n\n```typescript\n// component.component.ts\nexport class Component implements OnInit {\n  emailField: FormControl;\n  constructor() {\n    this.emailField =  new FormControl('', [\n      Validators.required,\n      Validators.maxLength(50),\n      Validators.minLength(4),\n      Validators.email,\n      Validators.pattern(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$/)\n    ]);\n  }\n}\n```\n\n```html\n\u003c!-- component.component.html --\u003e\n\u003cinput type=\"email\" [formControl]=\"emailField\"\u003e\n{{ emailField.valid }} \u003c!-- Imprime true o false si el input es válido --\u003e\n```\n\n\n\n# Reactive programming\n\n- [Rxjs](https://rxjs-dev.firebaseapp.com/guide/)\n- [Operators](https://rxjs-dev.firebaseapp.com/guide/operators)\n\n\n/*La sección ARRANGE de un método de prueba unitaria inicializa los objetos y establece el valor de los datos que se pasan al método bajo prueba.\n\nLa sección ACT invoca el método bajo prueba con los parámetros organizados.\n\nLa sección ASERT verifica que la acción del método bajo prueba se comporta como se esperaba. */\n### docker\n```\n docker run -d  -p 8080:80 -v /home/visaka/Documentos/estudio/angular-9-store/dist/store/:/usr/share/nginx/html nginx:alpine\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevdevi%2Fangular-9-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevdevi%2Fangular-9-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevdevi%2Fangular-9-store/lists"}