:toc: macro
toc::[]

= Angular Client Generation

The generation can create a full Angular client (Angular 13, as of March 2022) using the devon4ng-application-template package located at `workspaces/examples` folder of the distribution. For more details about this package, please refer link:https://github.com/devonfw/devon4ng-application-template[here].

Take into account that the TypeScript merging for CobiGen needs Node 6 or higher to be installed at your machine.

NOTE: This is a short introduction to the Angular generation. For a deeper tutorial including the generation of the backend, we strongly recommend you to follow link:files/HOW-TO-devonfw-ide-CobiGen-PoC-E2E_v3.2.pdf[this document].

== Requisites

Install yarn globally:

```
npm install -g yarn
```

== Angular workspace

The output location of the generation can be defined editing the `*__cobigen.properties__*` file located at *__crud_angular_client_app/templates__* folder of the *__CobiGen_Templates__* project.

image::images/howtos/angular4-gen/ng4gen_7.png[`cobigen.properties file`,width="450"link="images/howtos/angular4-gen/ng4gen_7.png"]

By default, the output path would be the __devon4ng-application-template__ folder at the root of the devon4j project parent folder: 

----
root/
 |- devon4ng-application-template/
 |- devon4j-project-parent/
   |- core/
   |- server/
----

However, this path can be changed, for example to the `__src/main/client__` folder of the devon4j project:

`relocate: ./src/main/client/${cwd}`

```
root/
 |- devon4j-project-parent/
   |- core/
      |- src
        |- main
          |- client
   |- server/
```


Once the output path is chosen, copy the files of the link:https://github.com/devonfw/devon4ng-application-template[devon4ng-application-template] repository into this output path. 

== Install Node dependencies

Open a terminal in the just copied `devon4ng-application-template` folder and run the command:

[source, bash]
yarn

This will start the installation of all node packages needed by the project into the `node_modules` folder.

== Generating

Choose an ETO object as an input file for CobiGen, right click on it and select CobiGen -> Generate from the context menu.
CobiGen will then display a wizard showing you the resources to be generated which are related to your input file:

image::images/howtos/angular4-gen/ng4gen_1.png[CobiGen Client Generation Wizard,width="450"link="images/howtos/angular4-gen/ng4gen_1.png"]

Check all the increments relative to Angular:

[NOTE]
=======
The Angular devon4j URL increment is only needed for the first generations however, checking it again on next generation will not cause any problem.
=======

As we have done on other generations, we click `Next` to choose which fields to include at the generation or simply clicking `Finish` will start the generation.

image::images/howtos/angular4-gen/ng4gen_3.png[CobiGen Client Generation Wizard 3,width="450"link="images/howtos/angular4-gen/ng4gen_3.png"]

== Routing

Due to the nature of the TypeScript merger, currently it is not possible to merge the array of path objects of the routings at `app-routing.module.ts` file properly, so the modification should be done by hand on this file. However, the import related to the new component generated is added.

This would be the generated `app-routing.module.ts` file:
[source, ts]
----
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './core/security/auth-guard.service';
import { NavBarComponent } from './layout/nav-bar/nav-bar.component';

const routes: Routes = [
  {
    path: '',
    redirectTo: '/login',
    pathMatch: 'full',
  },
  {
    path: 'login',
    loadChildren: () =>
      import('./auth/auth.module').then(m => m.AuthDataModule),
  },
  {
    path: 'home',
    component: NavBarComponent,
    canActivateChild: [AuthGuard],
    children: [
      {
        path: 'initial',
        loadChildren: () =>
          import('./home/initial-page/initial-page.module').then(
            m => m.InitialPageModule,
          ),
      },
      {
        path: 'sampleData',
        loadChildren: () =>
          import('./sampledata/sampledata.module').then(
            m => m.SampleDataModule,
          ),
      },
    ],
  },
  {
    path: '**',
    redirectTo: '/login',
  },
];
@NgModule({
  imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
  exports: [RouterModule],
})
export class AppRoutingModule {}
----

Adding the following to the children object of `home` will add a new side menu entry to the component generated:

[source, ts]
----
{
    path: 'employee',
    loadChildren: () =>
        import('./employee/employee.module').then(
            m => m.EmployeeModule,
        )
}
----

[source, ts]
----
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './core/security/auth-guard.service';
import { NavBarComponent } from './layout/nav-bar/nav-bar.component';


const routes: Routes = [{
        path: '',
        redirectTo: '/login',
        pathMatch: 'full'
    },
    {
        path: 'login',
        loadChildren: () =>
            import('./auth/auth.module').then(m => m.AuthDataModule)
    },
    {
        path: 'home',
        component: NavBarComponent,
        canActivateChild: [
            AuthGuard
        ],
        children: [{
                path: 'initial',
                loadChildren: () =>
                    import('./home/initial-page/initial-page.module').then(
                        m => m.InitialPageModule,
                    )
            },
            {
                path: 'sampleData',
                loadChildren: () =>
                    import('./sampledata/sampledata.module').then(
                        m => m.SampleDataModule,
                    )
            },
            {
                path: 'employee',
                loadChildren: () =>
                    import('./employee/employee.module').then(
                        m => m.EmployeeModule,
                    )
            }
        ]
    },
    {
        path: '**',
        redirectTo: '/login'
    }
];

@NgModule({
    imports: [
        RouterModule.forRoot(routes)
    ],
    exports: [
        RouterModule
    ]
})
export class AppRoutingModule {

}
----

image::images/howtos/angular4-gen/ng4gen_6.png[`APP SideMenu`,width="450"link="images/howtos/angular4-gen/ng4gen_6.png"]

== `JWT` Authentication

If you are using a backend server with `JWT` authentication, you need to specify this type of authentication to be used by your Angular application (default when generating from the devon4ng template).

.link:https://github.com/devonfw/devon4ng-application-template/blob/develop/src/environments/environment.ts[environment.ts]
```
export const environment = {
  ...,
  security: 'jwt',
};
```

An alternative would be to set `security: 'csrf'`. For more details, see the link:https://github.com/devonfw/devon4j/wiki/guide-csrf[devon4j CSRF guide].

== Running

First of all, run your devon4j java server by right clicking on the `SpringBootApp.java` file and choose Run As -> Java Application from the context menu. This will start to run the `SpringBoot` server. Once you see the statement: `Started SpringBoot in XX seconds`, the backend is running.

image::images/howtos/angular4-gen/ng4gen_4.png[Starting `SpringBoot`,width="450"link="images/howtos/angular4-gen/ng4gen_4.png"]

Once the the server is running, open a devonfw console at the output directory defined previously and run:

```
ng serve --open
```


This will run the Angular application at:

[source, URL]
----
http://localhost:4200
----

image::images/howtos/angular4-gen/ng4gen_5.png[Running Angular app,width="450"link="images/howtos/angular4-gen/ng4gen_5.png"]

Once finished, the browser will open automatically at the previously stated localhost URL showing the Angular application. You can use the credentials set at the devon4j java server to login.
