Ejemplo de una simple aplicación para publicar cursos virtuales y suscribirse a ellos de diferentes maneras, bien sea a través de un Subject, un BehaviorSubject o un ReplaySubject.
También se prueba la librería ngPrime (Primefaces para Angular).
Se puede suscribir a los cursos y ver los capítulos de los que consta.
Se comenta a continuación que es un subject y los 3 principales subjects que hay.
Demo aquí
Documentación aquí
Un subject actúa a la vez como observador y como un observable. Debido a que es un observador, puede suscribirse a uno o más observables, y porque es un observable, emitir valores a sus observers.
Por ejemplo un subject que emite el un valor a sus observers
let subject = new Subject <string>();
subject.next('1');
El subject se puede publicar como observable para poder ser observado
let subject = new Subject <string>();
// se publica como observable, ahora se pueden suscribir a sus emisiones
let subject$ = subject.asObservable();
let observer = subject$.subscribe (console.log)
subject.next('1');
subject.next('2');
....
Y tb podrá emitir error y complete
subject.error('Error forzado!');
subject.complete();
Todos los mencionados son subject pero difieren en los siguientes aspectos Cuando un observer se suscribe a un subject, este comienza a recibir eventos a partir de ese momento
let subject = new Subject <string>();
// se publica como observable, ahora se pueden suscribir a sus emisiones
let subject$ = this.subject.asObservable();
subject.next('1');
subject.next('2');
observer = this.subject$.subscribe(console.log);
subject.next('4');
subject.next('5');
//pintará por consola 4 y 5
subject.complete();
observer.unsubscribe();
Cuando un observer se suscribe a un BehaviorSubject este recibe el último valor emitido y todos lo valores que se emitan a continuación. El Behavior necesita de un valor inicial!
let behaviorSubject = new BehaviorSubject <string>('');
// se publica como observable, ahora se pueden suscribir a sus emisiones
let behaviorSubject$ = this.behaviorSubject.asObservable();
behaviorSubject.next('1');
behaviorSubject.next('2');
observer = this.behaviorSubject$.subscribe(console.log);
behaviorSubject.next('4');
behaviorSubject.next('5');
//pintará por consola 2, 4 y 5 (el 2 es el último valor prevcio a suscripción)
behaviorSubject.complete();
observer.unsubscribe();
Y cuando un observer se suscribe a un ReplaySubject este recibe todos los valores emitidos previamente y todos lo valores que se emitan a continuación
let replaySubject= new ReplaySubject<string>();
// se publica como observable, ahora se pueden suscribir a sus emisiones
let replaySubject$ = this._replaySubject.asObservable();
replaySubject.next('1');
replaySubject.next('2');
observer = replaySubject$.subscribe(console.log);
replaySubject.next('4');
replaySubject.next('5');
//pintará por consola 1, 2, 4 y 5
replaySubject.complete();
observer.unsubscribe();
Ver ejemplos en archivo ejemplo.component.ts . Ver resultado de consola aquí
La jerarquía de módulos se establece de la siguiente forma App (bootstrap->LayoutComponent)
- core (exporta LayoutComponent)
- cursos
- ejemplo-consola
El core.module encapsula la estructura principal de la aplicación a través del componente LayoutComponent. Lo hace visible al AppModule
exports: [
LayoutComponent
]
y hará el bootstrap de la aplicación en el AppModule
NgModule({
declarations: [],
imports: [
BrowserModule,
CoreModule,
FormsModule,
HttpModule,
.....
],
providers: [],
bootstrap: [LayoutComponent]
})
Este componente renderiza en su template simplemente el principal de la aplicación, ya que carecemos de menu
<router-outlet></router-outlet>
Los módulos son cargados dinámicamente. Se genera bundle (chunks) de cada uno y se cargan bajo demanda
const routes: Routes = [
{ path: 'ejemplo', loadChildren: 'app/ejemplo-consola/ejemplo-consola.module#EjemploConsolaModule'},
{ path: '', loadChildren: 'app/cursos/cursos.module#CursosModule' }
];
Para este ejemplo se utiliza ngPrime (Primefaces para Angular) Ver documentación aquí
Para instalar librerías
npm install primeng --save
npm install @angular/animations --save
npm install font-awesome --save
Añadir dependencias de css
"styles": [
"../node_modules/primeng/resources/primeng.min.css",
"../node_modules/primeng/resources/themes/omega/theme.css",
"../node_modules/font-awesome/css/font-awesome.min.css",
...
]
Importar animaciones en el módulo root app
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
....
y para cada componente que utilizemos, es necesario importar de igual forma el módulo correspondiente (para componente OrderList por ejemplo)
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
OrderListModule
En este caso lo meteremos en el cursos.module
Para mobile este evento de html nativo no es soportado, por ello incluimos un polyfill (DragDropTouch.js) en el angular-cli.json
"scripts": [
"../src/third-parts/DragDropTouch.js"
]
Ver Documentacion de la aplicación aqui
Instalación global
npm install -g @compodoc/compodoc
Instalación local
npm install --save-dev @compodoc/compodoc
Definir script en package.json (se añade -a screenshots para llevar la carpeta de screenshots al generado, y el theme)
"scripts": {
...
"compodoc": "./node_modules/.bin/compodoc -p tsconfig.json -a screenshots"
}
Lanzar script
npm run compodoc
Se genera carpeta /documentation
Se crea script en el package.json que borra /dist, genera el build para prod, documentación y despliega en firebase
"scripts": {
...
"compodoc": "./node_modules/.bin/compodoc -p tsconfig.json -a screenshots",
"deploy-firebase": "del dist && ng build --env=prod --aot && npm run compodoc && move documentation dist && firebase deploy"
}