Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

The Recipe for Angular 2 in a Java EE Environment: Frontend 1

DZone's Guide to

The Recipe for Angular 2 in a Java EE Environment: Frontend 1

In this post, we'll go over creating the Frontend and User-Interface (UI) aspects of your project using Angular 2 and Java EE.

· Web Dev Zone
Free Resource

Tips, tricks and tools for creating your own data-driven app, brought to you in partnership with Qlik.

This is the third article in our "The Recipe for Angular 2 in a Java EE Environment" series with a more detailed description of the Frontend of the Angular2 and JavaEE Project. It follows my second article about Angular 2 and Java EE that gave a detailed overview of the Backend of the Car Rental Project.

The Angular2 and JavaEE Project uses Angular-CLI to serve and build the UI. The project skeleton was provided by Angular-CLI (ng new car rental --routing). For translation, ngx-translate is used. It was ported from ng-translate of Angular 1. Angular's I18N will be used later. This article will go into the following subjects:

  • Modules
  • Routing

  • Setup of Ngx-Translate in the Bootstrap Component
  • A Listview

I'll demonstrate how to extend an Angular-CLI generated App to support Translation, 2 Routes, and a Listview. The generated parts from Angular-CLI are excluded because they are documented by Angular and Angular-CLI, and consist of common technologies. This article tries to provide a deeper introduction to Angular 2 with some basic integrated features. 

Application Setup

The Application Setup can be found in the app.module.ts file. The Application registers its main components, its modules (used application parts or features), the providers (services) and the bootstrap component to start. 

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule,ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { TranslateModule} from 'ng2-translate/ng2-translate';

import { AppComponent } from './app.component';
import { CrlistComponent } from './crlist/crlist.component';
import { CrdetailComponent } from './crdetail/crdetail.component';
import { CrValuesComponent } from './crvalues/crvalues.component';
import { CrRestService } from './crrest.service';
import { AppRoutingModule }  from './app-routing.module';

@NgModule({
  declarations: [
    AppComponent,
    CrlistComponent,
    CrdetailComponent,
    CrValuesComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule,
    TranslateModule.forRoot(),
    AppRoutingModule
  ],
  providers: [CrRestService],
  bootstrap: [AppComponent]
})
export class AppModule { }

In Lines 15-20, the Components are declared. 

In Lines 23-24, the Modules for From Validation are imported. 

In Lines 26, the Modules for Ngx-Translate are imported.

In Lines 27, the Routing Module is imported.

In Lines 29, the Restservice Class is registered as the provider.

In Lines 30, the Root Component for bootstrapping is registered.

Routing Setup

The Routing Setup can be found in the Class app-routing.modules.ts. It sets up the routes to the Listview and the Detailview. 

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CrlistComponent } from './crlist/crlist.component';
import { CrdetailComponent } from './crdetail/crdetail.component';

const routes: Routes = [
  {path: 'crdetail/mietenr/:mnr/jahr/:jahr', component: CrdetailComponent},
  {path: 'crlist/mietenr/:mnr', component: CrlistComponent}  
];

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

In Lines 7-8 the Routes are set up. The 'path' defines the URL Path of the Route and the Component of the Route is added. The Parameters that are used in the Components are ':mnr' and ':jahr.'

In Lines 11-16, you'll find the standard setup of the Routing Module.

Setup Ngx-Translate

In the bootstrap component, app.component.ts Ngx-Translate is setup with the language to use.

import { Component } from '@angular/core';
import {TranslateService, TranslatePipe, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate';


@Component({  
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'carrental works!';

  constructor(private _translate: TranslateService) {
    var userLang = navigator.language.split('-')[0]; // use navigator lang if available
    userLang = /(de|fr|it|en)/gi.test(userLang) ? userLang : 'en';
    this._translate.setDefaultLang('en');
    this._translate.use(userLang);
  }
}

In Lines 6-8, the Angular 2 Component is set up with the name of the template element, with the path to the template and the path to the CSS file.

In Line 14, the language of the browser is retrieved. 

In Line 15, the browser language is checked for the supported languages or English is set as the default.

In Lines 16-17, the language for Ngx-Translate is set.

The List Component

The List Component crlist.component.ts subscribes to the route and reads the parameters of the route. It reads the rest service with the route parameters and displays the values in a table.

import { Component, OnInit, OnDestroy } from '@angular/core';
import {ActivatedRoute, Router } from '@angular/router';
import {ISubscription} from 'rxjs/Subscription';
import {CrRestService} from '../crrest.service';
import {CrTableRow} from '../crTypes';

@Component({  
  selector: 'app-crlist',
  templateUrl: './crlist.component.html',
  styleUrls: ['./crlist.component.css'],    
})
export class CrlistComponent implements OnInit, OnDestroy {
  tableRows: CrTableRow[];
  errorMsg: string;
  private sub: ISubscription;
  private routeSub: ISubscription;

  constructor(private route: ActivatedRoute,private router: Router, private service: CrRestService) {}

  ngOnInit(): void {
      this.routeSub = this.route.params.subscribe(params => {
        let mnr = params['mnr'];
        this.sub = this.service.getCrTableRows(mnr).subscribe(tr => this.tableRows = <CrTableRow[]> tr, error => this.errorMsg = error);      
      });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
    this.routeSub.unsubscribe();
  }
}

Line 12 defines the Class CrlistComponent that implements the interfaces OnInit, OnDestroy.

Line 13 defines the tableRows member Array that is displayed in the template.

Lines 15-16 define the Subscriptions of the Route Params and the Service.

Line 18 is the constructor that gets the parameters/members injected by Angular that are annotated as injectable. 

Line 20 sets up the ngOnInit() method that gets called after the creation of the Component.

Line 21 subscribes to the Route Params with an Observable. The Observable puts the Parameters in the params variable.

Line 22 gets the Route Parameter 'mnr'.

Line 23 calls the CrRestservice with the 'mnr' Route Parameter and subscribes to its result. The result is the tr Array the gets set in the tableRows member. In the case of an Error, the error variable gets set. 

Lines 27-30 set up ngOnDestroy so it's called before a Components is discarded and unsubscribes the subscriptions of the Component. That is in these cases not really necessary but can serve as an example for subscriptions to changing input values. 

If the Observable is not put in a member it could be written:

this.service.getCrDetail(mnr, jahr).subscribe(...);

After the call, everything is cleaned up.

The Template of the ListView

The Template crlist.component.html of the ListView shows how the values of the list a displayed with translated headings. The English Translations are in the en.json file.

<div class="container-fluid">
    <div class="row">
        <p>crlist works!</p>
    </div>
    <div class="row">
        <table class="table table-striped borderless">
            <tr>
                <th class="col-md-1">{{'JAHR' | translate}}</th>
                <th class="col-md-1">{{'STATUS' | translate}}</th>
                <th class="col-md-1">{{'GRUND' | translate}}</th>
                <th class="col-md-1">{{'FAHRZEUGE_TOTAL' | translate}}</th>
                <th class="col-md-1">{{'MIETE_GEPLANT_TOTAL' | translate}}</th>
                <th class="col-md-1">{{'MIETE_ABGERECHNET_TOTAL' | translate}}</th>
                <th class="col-md-1">{{'ANZAHL_PKW' | translate}}</th>
                <th class="col-md-1">{{'ANZAHL_LKW' | translate}}</th>
                <th class="col-md-1">{{'DATUM' | translate}}</th>
                <th class="col-md-1">{{'CHANGED_BY' | translate}}</th>
                <th class="col-md-1">{{'MAHNSTOP' | translate}}</th>
            </tr>
            <tr *ngFor="let row of tableRows">
                <td class="col-md-1"><a [routerLink]="['/crdetail/mietenr',row.mietNr, 'jahr', row.jahr]">{{row.jahr}}</a>
                </td>
                <td class="col-md-1">{{row.status}}</td>
                <td class="col-md-1">{{row.grund}}</td>
                <td class="col-md-1">{{row.fahrzeugeTotal}}</td>
                <td class="col-md-1">{{row.mieteGeplantTotal}}</td>
                <td class="col-md-1">{{row.mieteAbgerechnetTotal}}</td>
                <td class="col-md-1">{{row.anzahlPkw}}</td>
                <td class="col-md-1">{{row.anzahlLkw}}</td>
                <td class="col-md-1">{{row.mutatedAt | date:'dd.MM.yyyy'}}</td>
                <td class="col-md-1">{{row.mutatedBy}}</td>
                <td class="col-md-1">
                    <input type="checkbox" [value]="row.mahnstop">
                </td>
            </tr>
        </table>
    </div>
</div>

Line 8 is an example of the translated header with '{{'key' | translate}}' Ngx-Translate Pipe Syntax. The en.json File has the JSON key-value pairs for the translation.

Line 20 has the for loop over the tableRows Component Member.

Line 21 shows a routerLink that provides a link to the DetailView with the Url concatenated of the parameters '/crdetail/mietenr', mietNr, 'jahr' and jahr. An example Url could look like: '/crdetail/mietenr/1/jahr/2015'. The Link String is defined by '{{row.jahr}}' that displays the jahr value of the row.

Line 29 shows the Date Pipe that formats the date according to the 'dd.MM.yyyy' format string.

Conclusion

For Developers with a Java background, the Syntax and the Concepts should look familiar. The strict typing, classes, and interfaces of Typescript that enable Ide support and compile checks. The Annotations for Configuration, the Module System, and the Observables are available in RxJava and can be learned in a familiar environment. The templates will look familiar to Java EE Developers. It is not the same, but it's very similar. You have to learn Typescript and Angular 2, but you can reuse a lot of your Java EE skills.

Upcoming

This is the end of the first part of the description of the Angular UI of the Angular2AndJavaEE Project. In the next UI Part the Service, its Types, the Detailview, its Validations and 2 Tests are shown.  

Angular2AndJavaEE now has a Project Diary that shows the current state of the Project and the planned features of the future.

Explore data-driven apps with less coding and query writing, brought to you in partnership with Qlik.

Topics:
java ee ,angular 2 ,web dev ,front end development ,ui design

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}