miércoles, 3 de marzo de 2021

UI5 Web Components con Angular 11

Habiendo desarrollado hace poco unos proyectos de gestión financiera, siempre estaba la discusión de que estilo que colores en la UI se iba a utilizar,  el framework a usar para Front End,  Back End, etc temas a discutir con maquetadores, diseñadores, áreas de usabilidad que casi siempre brillan por su ausencia ... etc etc etc.

así que investigando vi como un grande de los ERP, como SAP a evolucionado su plataforma hasta llegar a la web, y han creado OpenUI5 y UI5 Web Components, y me pareció muy útil , buena legibilidad, en su diseño, los tipos de fuentes, entre otras cosas

aquí dejo el link : UI5 Web Components






 









Ahora para usarlo en Angular, hay que instalar lo siguiente:

npm install @ui5/webcomponents
npm i @ui5/webcomponents-fiori

Para data binding, se ayuda de la librería Origami

npm install @codebakery/origami

Luego importamos los módulos dentro de app.module.ts



y para terminar de configurar hay que setear el schema  CUSTOM_ELEMENTS_SCHEMA

import { NgModuleCUSTOM_ELEMENTS_SCHEMAAPP_INITIALIZER } from '@angular/core';



@NgModule({
  declarations: [
    AppComponent,
    HomeComponent
  ],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  imports: [
    BrowserModule,
    OrigamiFormsModule,
    HttpClientModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule,
    LayoutsModule,
    AuthModule,
    SharedModule,
  ],
  providers: [
    {
        provide: APP_INITIALIZER,
        useFactory: onAppInit,
        multi: true
    },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }



Para el header de la página podemos usar el componente Shellbar


<ui5-shellbar id="shellbar" (click)="onShellBar($event)" primary-title="Optimus ERP"
 secondary-title="ESoftware"  show-co-pilot show-notifications
  show-product-switch>
  <ui5-avatar id="userInfo"  slot="profile" 
image="./../../../../assets/avatar/empty-user.jpg">
  </ui5-avatar>
  <ui5-button icon="nav-back" slot="startButton"></ui5-button>

  <ui5-button icon="menu" slot="startButton" id="startButton"></ui5-button>
</ui5-shellbar>


y para la navegación usamos el side-navigation


<ui5-side-navigation>
  <ui5-side-navigation-item text="Home" icon="home"  ></ui5-side-navigation-item>
  <ui5-side-navigation-item expanded    *ngFor="let item of UI_MENU_LIST" 
        [text]="item.Description" expanded [icon]="item.image">
    <ui5-side-navigation-sub-item  *ngFor="let menu of item.items"
         [text]="menu.Description"></ui5-side-navigation-sub-item>
  </ui5-side-navigation-item>
</ui5-side-navigation>



como pueden observar nos valemos de *ngFor, para mostrar los datos que vienen del servicio y obtenemos el poder de reactividad

en los input, para que funcione bien la reactividad al momento que usamos el :

formControlName="UserName"


se debería usar el atributo ngDefaultControl

 <ui5-input style="width: 100%" id="UserName" 
        placeholder="Enter your Name" required formControlName="UserName"
        ngDefaultControl origami></ui5-input>


y vamos a obtener una interfaz de este tipo:






personalmente veo una buena opción para no batallar mucho con el tema de estilos, formas, etc etc ya que aquí tenemos una presentación muy estilizada, profesional .. 

ahora un tema en contra, es que el equipo de UI5, esta trabajando en mejorar los componentes y la forma de trabajar con los eventos, no es como lo hacemos nativamente en Angular, si no como las viejas apps con java script.


en el ejemplo, en el componente ShellBar (Header), si quiero capturar el evento click , en Angular seria (click)="funcion()", si bien es cierto esto funciona, pero no capturamos el Handler del $event y lo tenemos que hacer en un js por separado y luego tenemos que inyectarlo 


El archivo .js quedaría como lo siguiente:


const load = function(){
  shellbar.addEventListener("profile-click"function (event) {
    //console.log(event.detail.targetRef);
    popover.openBy(event.detail.targetRef);
  });
}

module.exports = {load : load};

y en mi componente header.ts hacemos lo siguiente:

var h = require('./../header/header.js');



ngOnInit(): void {
     h.load();    
  }





Todo lo que describo en el post, está en la documentación, pero acá lo simplifico un poco.
espero sirva de ayuda