Crear un formulario de detalle
Introducción
En este tutorial se creará un nuevo componente (el formulario de detalle de un cliente) para poder visualizar los detalles de dicho cliente al hacer clic sobre el registro de la tabla correspondiente.
Crear el formulario de detalle
Mostrar, editar y borrar
Para crear el formulario de detalle, lo crearemos dentro del módulo de customers. Para ello, nos situamos en la terminal dentro del módulo de customers (a la altura del componente customers-home) y ejecutamos el comando de creación de componentes de Angular CLI:
npx ng g component --skip-tests customers-detail
(Más información acerca del comando aquí). Al terminar, tendremos una carpeta llamada customers-detail, que contendrá los archivos relacionados con el componente.
![](https://ontimizeweb.github.io/docs/v15/assets/images/tutorial_o_web_11.png)
- bankmanager-web
- e2e
- src
- app.e2e-spec.ts
- app.po.ts
- protractor.conf.js
- tsconfig.json
- src
- src
- app
- login
- login-routing.module.ts
- login.component.html
- login.component.scss
- login.component.ts
- login.module.ts
- login.theme.scss
- main
- customers
- customers-detail
- customers-detail.component.css
- customers-detail.component.html
- customers-detail.component.ts
- customers-home
- customers-home.component.css
- customers-home.component.html
- customers-home.component.ts
- customers-routing.module.ts
- customers.module.ts
- customers-detail
- home
- home-routing.module.ts
- home.component.html
- home.component.scss
- home.component.ts
- home.module.ts
- main-routing.module.ts
- main.component.html
- main.component.scss
- main.component.ts
- main.module.ts
- customers
- shared
- app.menu.config.ts
- app.services.config.ts
- shared.module.ts
- app-routing.module.ts
- app.component.html
- app.component.scss
- app.component.spec.ts
- app.component.ts
- app.config.ts
- app.module.ts
- login
- assets
- css
- app.scss
- loader.css
- i18n
- en.json
- es.json
- icons
- ontimize128.png
- ontimize16.png
- ontimize256.png
- ontimize32.png
- ontimize48.png
- ontimize64.png
- ontimize72.png
- ontimize96.png
- images
- login_bg.png
- no-image.png
- ontimize.png
- ontimize_web_log.png
- sidenav-closed.png
- sidenav-opened.png
- user_profile.png
- js
- domchange.js
- keyboard.js
- .gitkeep
- css
- environments
- environment.prod.ts
- environment.ts
- favicon.ico
- index.html
- main.ts
- manifest.webmanifest
- polyfills.ts
- styles.scss
- test.ts
- app
- .browserslistrc
- .editorconfig
- .eslintrc.json
- .gitignore
- angular.json
- karma.conf.js
- ngsw-config.json
- package-lock.json
- package.json
- README.md
- tsconfig.app.json
- tsconfig.json
- tsconfig.spec.json
- e2e
Modificamos el fichero customers.module.ts, añadiéndole el import del nuevo componente, y situándolo en el array de declaraciones. A su vez, establecemos la nueva ruta en el fichero customers-routing.module.ts. Para conocer la ruta que el componente tabla indicará para el detalle de cada uno de sus registros, tenemos que comprobar cual es el parámetro key
de la tabla para la cual queremos obtener el detalle (en este caso, tenemos que ver el parámetro key
de la tabla del fichero customers-home.component.html). Esto es así debido a que cuando naveguemos en la tabla, al abrir un registro, concatenará el valor de la columna definida en el atributo key
a la URL. Para definir ese comportamiento en el módulo de enrutamiento, precedemos el nombre de la columna por el símbolo de los dos puntos :
.
customers.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OntimizeWebModule } from 'ontimize-web-ngx';
import { CustomersRoutingModule } from './customers-routing.module';
import { CustomersHomeComponent } from './customers-home/customers-home.component';
import { CustomersDetailComponent } from './customers-detail/customers-detail.component';
@NgModule({
declarations: [
CustomersHomeComponent,
CustomersDetailComponent
],
imports: [
CommonModule,
OntimizeWebModule,
CustomersRoutingModule
]
})
export class CustomersModule { }
customers-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomersHomeComponent } from './customers-home/customers-home.component';
import { CustomersDetailComponent } from './customers-detail/customers-detail.component';
const routes: Routes = [{
path: '',
component: CustomersHomeComponent
},
{
path: ':CUSTOMERID',
component: CustomersDetailComponent
}];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomersRoutingModule { }
- bankmanager-web
- e2e
- src
- app.e2e-spec.ts
- app.po.ts
- protractor.conf.js
- tsconfig.json
- src
- src
- app
- login
- login-routing.module.ts
- login.component.html
- login.component.scss
- login.component.ts
- login.module.ts
- login.theme.scss
- main
- customers
- customers-detail
- customers-detail.component.css
- customers-detail.component.html
- customers-detail.component.ts
- customers-home
- customers-home.component.css
- customers-home.component.html
- customers-home.component.ts
- customers-routing.module.ts
- customers.module.ts
- customers-detail
- home
- home-routing.module.ts
- home.component.html
- home.component.scss
- home.component.ts
- home.module.ts
- main-routing.module.ts
- main.component.html
- main.component.scss
- main.component.ts
- main.module.ts
- customers
- shared
- app.menu.config.ts
- app.services.config.ts
- shared.module.ts
- app-routing.module.ts
- app.component.html
- app.component.scss
- app.component.spec.ts
- app.component.ts
- app.config.ts
- app.module.ts
- login
- assets
- css
- app.scss
- loader.css
- i18n
- en.json
- es.json
- icons
- ontimize128.png
- ontimize16.png
- ontimize256.png
- ontimize32.png
- ontimize48.png
- ontimize64.png
- ontimize72.png
- ontimize96.png
- images
- login_bg.png
- no-image.png
- ontimize.png
- ontimize_web_log.png
- sidenav-closed.png
- sidenav-opened.png
- user_profile.png
- js
- domchange.js
- keyboard.js
- .gitkeep
- css
- environments
- environment.prod.ts
- environment.ts
- favicon.ico
- index.html
- main.ts
- manifest.webmanifest
- polyfills.ts
- styles.scss
- test.ts
- app
- .browserslistrc
- .editorconfig
- .eslintrc.json
- .gitignore
- angular.json
- karma.conf.js
- ngsw-config.json
- package-lock.json
- package.json
- README.md
- tsconfig.app.json
- tsconfig.json
- tsconfig.spec.json
- e2e
Si hacemos clic en el registro de una tabla, se cargará el formulario del fichero customers-detail.component.html. A continuación modificaremos el contenido del fichero para conseguir un formulario similar al siguiente mockup.
Lo primero es establecer el layout de pestañas, para que cada nuevo registro que se consulte se añada a una pestaña nueva. Para ello, en el componente customers-home.component.html añadimos un o-form-layout-manager
customers-home.component.html
<o-form-layout-manager attr="customersHome" title="{{'CUSTOMERS' | oTranslate }}" separator=" " mode="tab" label-columns="NAME;SURNAME">
<o-table attr="customersTable" service="customers" entity="customer" keys="CUSTOMERID"
columns="CUSTOMERID;ID;PHOTO;NAME;SURNAME;STARTDATE;EMAIL"
visible-columns="ID;PHOTO;NAME;SURNAME;STARTDATE;EMAIL" query-rows="20">
<o-table-column attr="PHOTO" title="PHOTO" orderable="no" searchable="no" type="image" avatar="yes"
empty-image="assets/images/no-image.png" image-type="base64"></o-table-column>
<o-table-column attr="STARTDATE" title="STARTDATE" type="date" format="LL"></o-table-column>
<o-table-column attr="ID" title="ID" width="100px"></o-table-column>
</o-table>
</o-form-layout-manager>
o-form-layout-manager (atributos de o-form-layout-manager) | ||
---|---|---|
Atributo | Valor | Significado |
attr | customersHome | Establece un identificador al layout manager |
title | {{'CUSTOMERS' | oTranslate }} | Establece el título que tendrá la pestaña principal. En este caso se usa la interpolación de Angular, que intenta evaluar la cadena "CUSTOMERS" a traves del pipe "| oTranslate", que devuelve la cadena que se le pasa como entrada traducida al idioma en el que esté definida la aplicación. |
separator | "" | Separador que se usará entre las columnas en los títulos de las pestañas |
mode | tab | Modo en el que funcionará el o-form-layout-manager. En este caso, en modo pestañas |
label-columns | NAME;SURNAME | Columnas que usará para el título de cada una de las pestañas. Estas estarán separadas por la cadena definida en el atributo separator |
Ahora, en el fichero customers-detail.component.html, construiremos el formulario de detalle
customers-detail.component.html
<o-form attr="customerDetail" service="customers" entity="customer" keys="CUSTOMERID" header-actions="R;I;U;D"
show-header-navigation="no">
<o-text-input attr="CUSTOMERID" sql-type="INTEGER" enabled="no"></o-text-input>
<div fxLayout="row">
<div>
<o-image id="CUSTOMER_PHOTO" attr="PHOTO" empty-image="assets/images/no-image.png"
sql-type="OTHER"></o-image>
</div>
<o-column fxFlex title="CUSTOMER_PERSONAL_INFORMATION">
<div fxLayout="row" fxLayoutGap="8px">
<o-text-input fxFlex="40" attr="NAME" required="yes"></o-text-input>
<o-text-input fxFlex="40" attr="SURNAME" required="yes"></o-text-input>
<o-date-input fxFlex="20" attr="STARTDATE"></o-date-input>
</div>
<div fxLayout="row" fxLayoutGap="8px">
<o-nif-input fxFlex="40" attr="ID" required="yes"></o-nif-input>
<o-integer-input fxFlex="40" attr="PHONE" step="0" thousand-separator=" "></o-integer-input>
<o-combo fxFlex="20" attr="CUSTOMERTYPEID" service="customers" entity="customerType"
keys="CUSTOMERTYPEID" columns="CUSTOMERTYPEID;DESCRIPTION" visible-columns="DESCRIPTION"
value-column="CUSTOMERTYPEID"></o-combo>
</div>
<o-email-input attr="EMAIL"></o-email-input>
<o-text-input attr="ADDRESS"></o-text-input>
<div fxLayout="row" fxLayoutGap="8px">
<o-real-input fxFlex="50" attr="LONGITUDE" decimal-separator="," max-decimal-digits="10"
min-decimal-digits="0"></o-real-input>
<o-real-input fxFlex="50" attr="LATITUDE" decimal-separator="," max-decimal-digits="10"
min-decimal-digits="0"></o-real-input>
</div>
<o-textarea-input attr="COMMENTS"></o-textarea-input>
</o-column>
</div>
</o-form>
o-form (atributos de o-form) | ||
---|---|---|
Atributo | Valor | Significado |
service | customers | Ruta del servicio REST |
entity | customer | Entidad del servicio |
keys | CUSTOMERID | Claves de la entidad, separadas por ; |
header-actions | R;I;U;D | Botones de acción disponibles en la botonera para las operaciones CRUD estándar, separadas por ; . Las operaciones disponibles son R(Refrescar), I (Insertar), U (Actualizar), D (Borrar) |
show-header-navigation | no | Incluye botones de navegación en la botonera. No se incluyen cuando se encuentra en modo pestaña (definido por el componente o-form-layout-manager) |
o-text-input (atributos de o-text-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | CUSTOMERID | Identificador del campo |
sql-type | INTEGER | Indica el tipo de dato que contiene este campo. Se debe especificar la cadena del tipo de dato de esta lista |
enabled | no | Indica si el campo está habilitado o no |
required | yes/no | Indica si se requiere que este campo contenga valor |
Directivas de maquetación Angular Layout - Demo interactiva | ||
---|---|---|
Atributo | Valor | Significado |
fxLayout | row | Los componentes internos se colocan en forma de fila |
fxFlex | 50/40/20 | Ocupa el 50 / 40 / 20 % del ancho disponible del contenedor padre. Si no tiene valor, trata de ocupar todo el esté disponible |
fxLayoutGap | 8px | Mantiene una separación de 8px entre los elementos de este contenedor |
o-row y o-column (atributos de containers) | ||
---|---|---|
Atributo | Valor | Significado |
title | CUSTOMER_PERSONAL_INFORMATION | Etiqueta de la columna de título |
o-image (atributos de o-image) | ||
---|---|---|
Atributo | Valor | Significado |
attr | PHOTO | Identificador del campo |
empty-image | assets/images/no-image.png | Imagen mostrada cuando el componente no tiene valor. |
o-date-input (atributos de o-date-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | STARTDATE | Identificador del campo |
o-nif-input (atributos de o-nif-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | STARTDATE | Identificador del campo |
o-integer-input (atributos de o-integer-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | PHONE | Identificador del campo |
step | 1 | Número de incremento en los botones del campo |
grouping | no | Indica si se debe agrupar el número con los separadores de millar. |
o-combo (atributos de o-combo) | ||
---|---|---|
Atributo | Valor | Significado |
attr | CUSTOMERTYPEID | Identificador del campo |
service | customers | Ruta del servicio REST |
entity | customerType | Entidad del servicio |
keys | CUSTOMERTYPEID | Clave primaria de la entidad |
columns | CUSTOMERTYPEID;DESCRIPTION | Columnas de la entidad que se consulta |
visible-columns | DESCRIPTION | Columnas visibles |
value-column | CUSTOMERTYPEID | Columna de la entidad de las que el componente obtiene el valor |
o-email-input (atributos de o-email-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | Identificador del campo |
o-real-input (atributos de o-real-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | LONGITUDE | Identificador de campo |
decimal-separator | , | Separador decimal |
max-decimal-digits | 10 | Máximos dígitos decimales |
min-decimal-digits | 0 | Mínimos dígitos decimales |
o-textarea-input (atributos de o-textarea-input) | ||
---|---|---|
Atributo | Valor | Significado |
attr | COMMENTS | Identificador de campo |
A continuación, se incluyen las nuevas traducciones para el formulario de detalle.
en.json
{
...
"CUSTOMER_PERSONAL_INFORMATION": "Personal Information",
"CUSTOMERID": "Customer Id.",
"PHONE": "Phone",
"CUSTOMERTYPEID": "Customer type",
"ADDRESS": "Address",
"LONGITUDE": "Longitude",
"LATITUDE": "Latitude",
"COMMENTS": "Comments"
}
es.json
{
...
"CUSTOMER_PERSONAL_INFORMATION": "Información personal",
"CUSTOMERID": "Id. cliente",
"PHONE": "Teléfono",
"CUSTOMERTYPEID": "Tipo cliente",
"ADDRESS": "Dirección",
"LONGITUDE": "Longitud",
"LATITUDE": "Latitud",
"COMMENTS": "Comentarios"
}
- bankmanager-web
- e2e
- src
- app.e2e-spec.ts
- app.po.ts
- protractor.conf.js
- tsconfig.json
- src
- src
- app
- login
- login-routing.module.ts
- login.component.html
- login.component.scss
- login.component.ts
- login.module.ts
- login.theme.scss
- main
- customers
- customers-detail
- customers-detail.component.css
- customers-detail.component.html
- customers-detail.component.ts
- customers-home
- customers-home.component.css
- customers-home.component.html
- customers-home.component.ts
- customers-routing.module.ts
- customers.module.ts
- customers-detail
- home
- home-routing.module.ts
- home.component.html
- home.component.scss
- home.component.ts
- home.module.ts
- main-routing.module.ts
- main.component.html
- main.component.scss
- main.component.ts
- main.module.ts
- customers
- shared
- app.menu.config.ts
- app.services.config.ts
- shared.module.ts
- app-routing.module.ts
- app.component.html
- app.component.scss
- app.component.spec.ts
- app.component.ts
- app.config.ts
- app.module.ts
- login
- assets
- css
- app.scss
- loader.css
- i18n
- en.json
- es.json
- icons
- ontimize128.png
- ontimize16.png
- ontimize256.png
- ontimize32.png
- ontimize48.png
- ontimize64.png
- ontimize72.png
- ontimize96.png
- images
- login_bg.png
- no-image.png
- ontimize.png
- ontimize_web_log.png
- sidenav-closed.png
- sidenav-opened.png
- user_profile.png
- js
- domchange.js
- keyboard.js
- .gitkeep
- css
- environments
- environment.prod.ts
- environment.ts
- favicon.ico
- index.html
- main.ts
- manifest.webmanifest
- polyfills.ts
- styles.scss
- test.ts
- app
- .browserslistrc
- .editorconfig
- .eslintrc.json
- .gitignore
- angular.json
- karma.conf.js
- ngsw-config.json
- package-lock.json
- package.json
- README.md
- tsconfig.app.json
- tsconfig.json
- tsconfig.spec.json
- e2e
Este será el aspecto final del formulario:
Insertar
Para insertar un nuevo registro, hay que indicar en el módulo de rutas cual es el componente que se usará para mostrar el formulario. Se puede usar un componente existente, o se puede crear uno nuevo específico. En este ejemplo crearemos un nuevo componente, donde usaremos un formulario prácticamente idéntico al del detalle. Volveremos a crear un nuevo componente mediante la línea de comando:
npx ng g component --skip-tests customers-new
![](https://ontimizeweb.github.io/docs/v15/assets/images/tutorial_o_web_14.png)
- bankmanager-web
- e2e
- src
- app.e2e-spec.ts
- app.po.ts
- protractor.conf.js
- tsconfig.json
- src
- src
- app
- login
- login-routing.module.ts
- login.component.html
- login.component.scss
- login.component.ts
- login.module.ts
- login.theme.scss
- main
- customers
- customers-detail
- customers-detail.component.css
- customers-detail.component.html
- customers-detail.component.ts
- customers-home
- customers-home.component.css
- customers-home.component.html
- customers-home.component.ts
- customers-new
- customers-new.component.css
- customers-new.component.html
- customers-new.component.ts
- customers-routing.module.ts
- customers.module.ts
- customers-detail
- home
- home-routing.module.ts
- home.component.html
- home.component.scss
- home.component.ts
- home.module.ts
- main-routing.module.ts
- main.component.html
- main.component.scss
- main.component.ts
- main.module.ts
- customers
- shared
- app.menu.config.ts
- app.services.config.ts
- shared.module.ts
- app-routing.module.ts
- app.component.html
- app.component.scss
- app.component.spec.ts
- app.component.ts
- app.config.ts
- app.module.ts
- login
- assets
- css
- app.scss
- loader.css
- i18n
- en.json
- es.json
- icons
- ontimize128.png
- ontimize16.png
- ontimize256.png
- ontimize32.png
- ontimize48.png
- ontimize64.png
- ontimize72.png
- ontimize96.png
- images
- login_bg.png
- no-image.png
- ontimize.png
- ontimize_web_log.png
- sidenav-closed.png
- sidenav-opened.png
- user_profile.png
- js
- domchange.js
- keyboard.js
- .gitkeep
- css
- environments
- environment.prod.ts
- environment.ts
- favicon.ico
- index.html
- main.ts
- manifest.webmanifest
- polyfills.ts
- styles.scss
- test.ts
- app
- .browserslistrc
- .editorconfig
- .eslintrc.json
- .gitignore
- angular.json
- karma.conf.js
- ngsw-config.json
- package-lock.json
- package.json
- README.md
- tsconfig.app.json
- tsconfig.json
- tsconfig.spec.json
- e2e
En este componente, se creará un formulario idéntico al de detalle, excepto por que desaparece el campo del Id. de cliente
customers-new.component.html
<o-form attr="customerDetail" service="customers" entity="customer" keys="CUSTOMERID" header-actions="R;I;U;D"
show-header-navigation="no">
<div fxLayout="row">
<div>
<o-image id="CUSTOMER_PHOTO" attr="PHOTO" empty-image="assets/images/no-image.png"
sql-type="OTHER"></o-image>
</div>
<o-column fxFlex title="CUSTOMER_PERSONAL_INFORMATION">
<div fxLayout="row" fxLayoutGap="8px">
<o-text-input fxFlex="40" attr="NAME" required="yes"></o-text-input>
<o-text-input fxFlex="40" attr="SURNAME" required="yes"></o-text-input>
<o-date-input fxFlex="20" attr="STARTDATE"></o-date-input>
</div>
<div fxLayout="row" fxLayoutGap="8px">
<o-nif-input fxFlex="40" attr="ID" required="yes"></o-nif-input>
<o-integer-input fxFlex="40" attr="PHONE" step="0" thousand-separator=" "></o-integer-input>
<o-combo fxFlex="20" attr="CUSTOMERTYPEID" service="customers" entity="customerType"
keys="CUSTOMERTYPEID" columns="CUSTOMERTYPEID;DESCRIPTION" visible-columns="DESCRIPTION"
value-column="CUSTOMERTYPEID"></o-combo>
</div>
<o-email-input attr="EMAIL"></o-email-input>
<o-text-input attr="ADDRESS"></o-text-input>
<div fxLayout="row" fxLayoutGap="8px">
<o-real-input fxFlex="50" attr="LONGITUDE" decimal-separator="," max-decimal-digits="10"
min-decimal-digits="0"></o-real-input>
<o-real-input fxFlex="50" attr="LATITUDE" decimal-separator="," max-decimal-digits="10"
min-decimal-digits="0"></o-real-input>
</div>
<o-textarea-input attr="COMMENTS"></o-textarea-input>
</o-column>
</div>
</o-form>
Declaramos cuál es el nuevo módulo, y la ruta para el que se usará este nuevo componente
customers.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OntimizeWebModule } from 'ontimize-web-ngx';
import { CustomersRoutingModule } from './customers-routing.module';
import { CustomersHomeComponent } from './customers-home/customers-home.component';
import { CustomersDetailComponent } from './customers-detail/customers-detail.component';
import { CustomersNewComponent } from './customers-new/customers-new.component';
@NgModule({
declarations: [
CustomersHomeComponent,
CustomersDetailComponent,
CustomersNewComponent
],
imports: [
CommonModule,
OntimizeWebModule,
CustomersRoutingModule
]
})
export class CustomersModule { }
customers-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CustomersHomeComponent } from './customers-home/customers-home.component';
import { CustomersDetailComponent } from './customers-detail/customers-detail.component';
import { CustomersNewComponent } from './customers-new/customers-new.component';
const routes: Routes = [{
path: '',
component: CustomersHomeComponent
},
{
path: "new",
component: CustomersNewComponent
},
{
path: ':CUSTOMERID',
component: CustomersDetailComponent
}];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomersRoutingModule { }
- bankmanager-web
- e2e
- src
- app.e2e-spec.ts
- app.po.ts
- protractor.conf.js
- tsconfig.json
- src
- src
- app
- login
- login-routing.module.ts
- login.component.html
- login.component.scss
- login.component.ts
- login.module.ts
- login.theme.scss
- main
- customers
- customers-detail
- customers-detail.component.css
- customers-detail.component.html
- customers-detail.component.ts
- customers-home
- customers-home.component.css
- customers-home.component.html
- customers-home.component.ts
- customers-new
- customers-new.component.css
- customers-new.component.html
- customers-new.component.ts
- customers-routing.module.ts
- customers.module.ts
- customers-detail
- home
- home-routing.module.ts
- home.component.html
- home.component.scss
- home.component.ts
- home.module.ts
- main-routing.module.ts
- main.component.html
- main.component.scss
- main.component.ts
- main.module.ts
- customers
- shared
- app.menu.config.ts
- app.services.config.ts
- shared.module.ts
- app-routing.module.ts
- app.component.html
- app.component.scss
- app.component.spec.ts
- app.component.ts
- app.config.ts
- app.module.ts
- login
- assets
- css
- app.scss
- loader.css
- i18n
- en.json
- es.json
- icons
- ontimize128.png
- ontimize16.png
- ontimize256.png
- ontimize32.png
- ontimize48.png
- ontimize64.png
- ontimize72.png
- ontimize96.png
- images
- login_bg.png
- no-image.png
- ontimize.png
- ontimize_web_log.png
- sidenav-closed.png
- sidenav-opened.png
- user_profile.png
- js
- domchange.js
- keyboard.js
- .gitkeep
- css
- environments
- environment.prod.ts
- environment.ts
- favicon.ico
- index.html
- main.ts
- manifest.webmanifest
- polyfills.ts
- styles.scss
- test.ts
- app
- .browserslistrc
- .editorconfig
- .eslintrc.json
- .gitignore
- angular.json
- karma.conf.js
- ngsw-config.json
- package-lock.json
- package.json
- README.md
- tsconfig.app.json
- tsconfig.json
- tsconfig.spec.json
- e2e