Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modern Web Apps with Spring Boot & Angular

Kai Toedter
November 11, 2022

Modern Web Apps with Spring Boot & Angular

This is the slide deck for my training "Modern Web Apps with Spring Boot & Angular". You find more information in English and German at http://toedter.com/cool-web-apps-training/. This slide deck is licensed under a Creative Commons Attribution 4.0 International License.

Kai Toedter

November 11, 2022
Tweet

More Decks by Kai Toedter

Other Decks in Programming

Transcript

  1. Modern Web Apps with Spring Boot & Angular Kai Tödter

    11/11/2022 1 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  2. Who am I? ▪ Principal Key Expert at Siemens Smart

    Infrastructure ▪ Web Technology Fan ▪ Open Source Lover ▪ E-mail: [email protected] ▪ Twitter: twitter.com/kaitoedter ▪ Mastodon: https://mastodon.social/@kaitoedter 11/11/2022 2 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  3. Show Hands! 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 3
  4. Spring Boot? Hypermedia? TypeScript? Angular? Bootstrap? 11/11/2022 © Kai Tödter,

    Licensed under a Creative Commons Attribution 4.0 International License. 4
  5. After this tutorial I’ll have an idea how to put

    it all together! 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 5
  6. Outline ▪ Spring Boot ▪ REST & Hypermedia ▪ Spring

    Data REST ▪ TypeScript ▪ Angular ▪ Bootstrap ▪ Putting it all together 11/11/2022 6 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  7. What we will create… 11/11/2022 © Kai Tödter, Licensed under

    a Creative Commons Attribution 4.0 International License. 7
  8. Requirements: Labs on local Machine ▪ Your favorite text editor

    or IDE ▪ Eclipse, IntelliJ IDEA, Sublime, … ▪ Java >= 11 (JDK) installed ▪ Node.js installed 11/11/2022 8 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  9. Lab 0: Check Build Environment ▪ Install the tutorial sources

    ▪ Clone https://github.com/toedter/webapp-tutorial ▪ Open terminal and cd into webapp-tutorial ▪ gradlew build ▪ Linux & Mac: ./gradlew build ▪ If the build is successful, you are ready to go! 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 9
  10. Optional: Try out Gidpod ▪ Open https://gitpod.io/#https://github.com/toedter/webapp-tutorial in Web browser

    ▪ Log-in using GitHub 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 10
  11. Gitpod Ready to Go! 11/11/2022 © Kai Tödter, Licensed under

    a Creative Commons Attribution 4.0 International License. 11
  12. Why Spring Boot? ▪ Fast way to build web applications

    ▪ Inspects your classpath and beans you have configured ▪ You can focus more on business features and less on infrastructure ▪ Easily deployable as microservice 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 13
  13. What does Spring Boot NOT? ▪ Generate code ▪ Change

    your configuration 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 14
  14. HelloController @RestController public class HelloController { @RequestMapping("/") public String index()

    { return "Greetings from Spring Boot!"; } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 15
  15. Application @SpringBootApplication public class Application { public static void main(String[]

    args) { SpringApplication .run(Application.class, args); } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 16
  16. Controller Test with MockMVC @WebMvcTest(HelloController.class) public class HelloControllerTest { @Autowired

    private MockMvc mockMVC; @Test public void shouldGetGreeting() throws Exception { mockMVC.perform(MockMvcRequestBuilders.get("/") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string(equalTo( HelloController.LAB1_GREETINGS_FROM_SPRING_BOOT))); } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 17
  17. Integration Test with Random Port @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class

    HelloControllerIntegrationTest { @Autowired private TestRestTemplate restTemplate; @Test public void shouldGetGreeting() throws Exception { ResponseEntity<String> response = restTemplate.getForEntity("/", String.class); assertThat(response.getBody(), equalTo(HelloController.LAB1_GREETINGS_FROM_SPRING_BOOT)); } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 18
  18. Lab 1: Task 1 ▪ Open lab1/complete in your IDE

    ▪ Run Application.java ▪ Open browser with localhost:8080 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 19
  19. Lab 1: Task 2 ▪ Open lab1/initial in your IDE

    ▪ Create a Spring Boot based web app ▪ Run it and open your browser with localhost:8080 ▪ Optional: Write some tests! ▪ Get some ideas from …/complete 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 20
  20. 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 21 REST + Hypermedia Basics
  21. Outline ▪ REST Basics ▪ HATEOAS ▪ Hypermedia with HAL

    ▪ Spring Data REST 11/11/2022 22 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  22. What is REST? ▪ Stands for Representational State Transfer ▪

    Is a Software Architecture Style ▪ was introduced and defined in 2000 by Roy T. Fielding in his doctoral dissertation ▪ REST != CRUD via HTTP 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 23
  23. REST Architectural Constraints ▪ Client-Server ▪ Stateless ▪ Cacheable ▪

    Layered system ▪ Code on demand (optional) ▪ Uniform interface (see next slide) 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 24
  24. Uniform Interface ▪ Identification of resources ▪ Manipulation of resources

    through their representations ▪ Create => HTTP POST ▪ Read => HTTP GET ▪ Update => HTTP PUT, HTTP PATCH ▪ Delete => HTTP DELETE ▪ Self-descriptive messages ▪ Hypermedia as the engine of application state (HATEOAS) 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 25
  25. Richardson Maturity Model Level 3: Hypermedia Controls Level 2: HTTP

    Verbs Level 1: Resources Level 0: The Swamp of POX 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 26 Source: https://martinfowler.com/articles/richardsonMaturityModel.html
  26. Hypermedia APIs for Services are like Web Pages with Links

    for Humans 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 27
  27. 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 28 HAL Image Source: http://wallpoper.com/images/00/26/43/92/hal-9000_00264392.jpg
  28. HAL ▪ Is for Hypertext Application Language ▪ Was created

    by Mike Kelly ▪ Representations for both JSON and XML ▪ Very popular 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 29
  29. HAL Structure 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 30 Plain old JSON Properties Links Plain old JSON Properties Links Plain old JSON Properties Links … Embedded Resources Embedded Resources Embedded Resources
  30. HAL Example { "id":1, "text":"hello all!", "_links": { "self": {

    "href":"http://localhost:8080/chatty/api/messages/1" } }, "_embedded": { "author": { "id":"toedter_k" } } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 31
  31. Spring ▪ Spring Boot ▪ Spring Data REST ▪ Spring

    HATEOAS 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 32
  32. Spring Data Rest: Domain @Data @Entity @NoArgsConstructor public class User

    { @Id private String id; private String fullName; private String email; } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 33
  33. Spring Data REST: Repository @RepositoryRestResource( collectionResourceRel = "users", path =

    "users") interface UserRepository extends PagingAndSortingRepository<User, String> { } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 34
  34. Spring Data REST: Repository (2) @RepositoryRestResource( exported = false )

    interface UserRepository extends PagingAndSortingRepository<User, String> { } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 35
  35. Spring Data REST: JSON Result { _links: { self: {

    href: "http://localhost:8080/chatty/api/users{?page,size,sort}", templated: true } }, _embedded: { users: [ { fullName: "Jane Doe", email: "[email protected]", _links: { self: { href: "http://localhost:8080/chatty/api/users/doe_ja" }, … 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 36
  36. Robust Clients ▪ Start from main API ▪ Find link

    relations through defined contracts ▪ Follow Links ▪ For navigation ▪ For possible “actions” => Clients are robust regarding changes in link URIs 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 37
  37. Controversial Discussion ▪ Are we there yet? ▪ RESTistential Crises

    ▪ http://www.infoq.com/news/2014/03/rest-at- odds-with-web-apis ▪ DHH, Getting hyper about hypermedia apis ▪ https://signalvnoise.com/posts/3373-getting- hyper-about-hypermedia-apis 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 38
  38. Live Demo + Tests 11/11/2022 © Kai Tödter, Licensed under

    a Creative Commons Attribution 4.0 International License. 39
  39. Lab 2: Task 1 ▪ Open lab2/complete in your IDE

    ▪ Run Application.java ▪ Open browser with localhost:8080 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 40
  40. Lab 2: Task 2 ▪ Open lab2/initial in your IDE

    ▪ Add a user repository ▪ Fill the repository with test data ▪ Run the application and open your browser with localhost:8080 ▪ Optional: Write some tests! ▪ Get some ideas from ../complete 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 41
  41. 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 42 TypeScript & Angular
  42. Outline ▪ TypeScript Introduction ▪ Angular Introduction ▪ TypeScript +

    Angular ▪ Demos & Live Coding 11/11/2022 43 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  43. JavaScript? Many Java/OO developers don’t like JavaScript regarding writing larger

    applications. Some reasons are: ▪ No static typing ▪ No reliable code completion (only best guess) ▪ Hard to refactor ▪ Not object-oriented, especially ▪ No structuring mechanisms like Interfaces, Classes*, Modules* * Before ECMAScript 2015 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 44
  44. Who fixes that? ▪ Dart ▪ Great language by Google:

    dartlang.org ▪ Team has to learn new language ▪ Either runs on Dart VM or compiles to JavaScript ▪ CoffeeScript ▪ Ruby-like, concise syntax ▪ Compiles to JavaScript ▪ coffeescript.org ▪ BabelJS ▪ JavaScript compiler ▪ babeljs.io ▪ Traceur ▪ JavaScript compiler ▪ github.com/google/traceur-compiler 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 45
  45. TypeScript: Summary ▪ Typed Superset of JavaScript ▪ Almost all

    valid JavaScript is valid TypeScript* ▪ Compiles to JavaScript ▪ Provides optional static type checking at compile time ▪ For most existing JavaScript libraries there are type definitions available ▪ Provides Interfaces, Classes, Modules, Enums, Generics, Decorators and more ▪ Open Source: Apache 2.0 License ▪ Created by Microsoft 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 46
  46. How to get started? ▪ www.typescriptlang.org ▪ Install Node.js (nodejs.org)

    ▪ Invoke “npm install –g typescript” ▪ Compile a TypeScript file: “tsc myTypeScript.ts” ▪ Results in “myTypeScript.js” 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 47
  47. Play! 11/11/2022 © Kai Tödter, Licensed under a Creative Commons

    Attribution 4.0 International License. 49
  48. Definitely Typed 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 50
  49. Interfaces export interface User { getId(): string; getEmail(): string; getFullName():

    string; } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 51
  50. Classes export class SimpleUser implements User { constructor(private id: string,

    private email: string, private fullName: string) { } getId(): string { return this.id; } … 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 52
  51. Live Demo 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 53
  52. 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 54 JavaScript Dev Tools
  53. JavaScript Dev Tools ▪ In JavaScript land, mostly JavaScript based

    tools are used for build, dependency management, test, etc. ▪ npm (or yarn) for ▪ dependency management (including @types) ▪ Running build/test/server scripts ▪ Jasmine for implementing tests ▪ Karma for running tests 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 55
  54. npm ▪ Package manager for JavaScript ▪ Resolves dependencies ▪

    Runs scripts ▪ Input file is package.json ▪ Alternative to npm: yarn 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 56
  55. package.json Example (1) { "name": "tutorial-web-client", "title": "tutorial web client",

    "version": "1.0.0", "description": "tutorial web client", "scripts": { "build": "tsc", "test": "karma start" }, "author": { "name": "Kai Toedter", "url": "http://toedter.com" }, 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 57
  56. package.json Example (2) "license": "MIT", "dependencies": { }, "devDependencies": {

    "jasmine-core": "~4.4.0", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.1.1", "karma-coverage-istanbul-reporter": "~3.0.3", "karma-jasmine": "~5.1.0", "karma-coverage": "~2.2.0", "karma-jasmine-html-reporter": "^2.0.0", "typescript": "~4.8.2" } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 58
  57. Jasmine Example describe('User', () => { it('should create user and

    get attributes', () => { var user:User = new SimpleUser("user1", "[email protected]", "User 1"); expect(user).toBeDefined(); expect(user.getId()).toBe('user1'); expect(user.getEmail()).toBe(' [email protected] '); expect(user.getFullName()).toBe('User 1'); }); }); 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 59
  58. Since TypeScript 2.0: @types ▪ All typings are available as

    npm modules ▪ Install a typing with ▪ npm install @types/<npm module> ▪ E.g., npm install @types/jasmine 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 60
  59. @types in tsconfig.json { "compilerOptions": { "module": "es2020 ", "target":

    "es2020 ", "outDir": "build/dist", "rootDir": ".", "sourceMap": true, "experimentalDecorators": true, "moduleResolution": "node", "typeRoots": [ "node_modules/@types" ] } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 61
  60. Karma ▪ Test runner for JavaScript ▪ Created by Google

    ▪ Supports different browsers ▪ Easy configuration 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 62
  61. Karma Config Example module.exports = function(config) { config.set({ basePath: '.',

    frameworks: [ 'jasmine‘ ], files: [ 'dist/**/*.js' ], reporters: ['progress'], port: 9876, colors: true, autoWatch: false, browsers: ['Chrome'], singleRun: true, concurrency: Infinity }) } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 63
  62. Lab 3: Task 1 ▪ Open terminal in lab3/complete ▪

    export CHROME_BIN=/usr/bin/chromium-browser ▪ Invoke npm run build ▪ Check that all TypeScript files were transpiled to JavaScript in the dist directory ▪ Invoke npm test ▪ Check that the Karma run was successful ▪ And all Jasmine tests are green 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 64
  63. Lab 3: Task 2 ▪ Complete initial implementation of ▪

    User.ts, SimpleUser.ts, TestData.ts ▪ UserSpec.ts ▪ Open terminal in lab3/initial ▪ Invoke npm run build ▪ Check everything builds ▪ Invoke npm test ▪ Check that all tests are green 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 65
  64. Angular ▪ Angular is a framework for building client applications

    in HTML ▪ TypeScript, JavaScript, Dart ▪ Modules, Components, Templates, Services ▪ Much more… 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 68
  65. Modules ▪ Every Angular app has at least one module,

    the root module ▪ Conventionally named AppModule ▪ A module is a class with an @NgModule decorator 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 69
  66. @NgModule ▪ declarations ▪ view classes (components, directives, and pipes)

    of this module ▪ exports ▪ subset of declarations usable by other modules ▪ imports ▪ exported classes of other modules needed by component templates this module’s templates ▪ providers ▪ creators of services (globally accessible in all parts of the app) ▪ bootstrap ▪ main application view (root component) ▪ Only the root module should set this bootstrap property 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 70
  67. Example Module import {NgModule} from '@angular/core'; import {AppComponent} from './app.component';

    import {BrowserModule} from '@angular/platform-browser'; import {LocationStrategy, HashLocationStrategy} from '@angular/common'; @NgModule({ declarations: [AppComponent], imports : [BrowserModule], providers : [{ provide: LocationStrategy, useClass: HashLocationStrategy }], bootstrap : [AppComponent] }) export class AppModule {} 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 71
  68. Angular Libraries ▪ Angular ships as a collection of Node.js

    modules ▪ Can be found in node_modules/@angular ▪ common ▪ compiler ▪ core ▪ forms ▪ platform-browser ▪ platform-browser-dynamic ▪ router ▪ … 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 72
  69. Launching the App ▪ … by bootstrapping its root module

    import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {AppModule} from './app/app.module'; platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err)); 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 73
  70. Components ▪ A component controls a view ▪ In our

    tutorial, we have 3 components: ▪ AppComponent ▪ UsersComponent ▪ AboutComponent 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 74
  71. @Component ▪ Takes configuration to ▪ create and present the

    component and its view. ▪ A few @Component configuration options: ▪ selector ▪ CSS selector for this component ▪ Here: <chat-messages></chat-messages> ▪ Angular renders the templateURl between those tags ▪ templateUrl ▪ address of this component's HTML template ▪ providers ▪ array of dependency injection providers for services that the component requires 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 75
  72. Component Example import {Component} from '@angular/core'; import {User} from './user';

    import {UsersService} from './users.service'; @Component({ selector: 'app-users', templateUrl: 'app/user/users.component.html', providers: [UsersService], }) export class UsersComponent implements OnInit { private users: User[]; constructor(private usersService: UsersService) { } ngOnInit() { this.users = this.usersService.getUsers(); } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 76
  73. Templates ▪ A component's view is defined by a template

    ▪ A template looks like regular HTML, but can use Angular specific things 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 77
  74. User List Template <div> <h4>Users</h4> <table> <tr *ngFor="let user of

    users"> <td>{{user.id}}</td> <td>{{user.fullName}}</td> <td>{{user.email}}</td> </tr> </table> </div> 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 78
  75. One Way Databinding ▪ Component -> DOM ▪ interpolation: {{user.id}}

    ▪ Property binding: ▪ <user-detail [user]="selectedUser"></user-detail> ▪ DOM -> Component ▪ <li (click)="selectUser(user)"></li> 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 79
  76. Two Way Databinding ▪ Component <-> DOM ▪ <input [(ngModel)]="user.name">

    Recommendation: Prefer one way databinding, since it makes control flows easier to understand 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 80
  77. Dependency Injection ▪ Used everywhere in Angular ▪ injector is

    the main mechanism ▪ An injector maintains a container of service instances ▪ service instances are created automatically by the injector ▪ An injector can create a new service instance from a provider ▪ A provider is a recipe for creating a service ▪ Register providers with injectors ▪ Either in modules ▪ Or in components 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 81
  78. Services ▪ Are POTOs (Plain Old Typescript Objects) ▪ Should

    encapsulate functionality that can be uses by ▪ Other services ▪ Components 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 82
  79. Example Service import {Injectable} from '@angular/core'; import {User} from './user';

    @Injectable() export class UsersService { public getUsers(): User[] { return [ new User('toedter_k', 'Kai Toedter', '[email protected]'), new User('doe_jo', 'John Doe', '[email protected]'), new User('doe_ja', 'Jane Doe', '[email protected]') ]; } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 83
  80. @Injectable ▪ Needed by services, that want to have other

    services injected ▪ Recommendation: Use it for every service, even if it would not be necessary. Why? ▪ Future proofing: No need to remember @Injectable() when you add a dependency later ▪ Consistency: All services follow the same rules, and you don't have to wonder why a decorator is missing 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 84
  81. Singleton Service ▪ Best practice since Angular 6 ▪ Then

    you don’t have to specify a provider explicitly @Injectable({ providedIn: 'root' }) export class UsersService { // … } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 85
  82. Routing ▪ Tell the router how to compose navigation URLs,

    set base in index.html, e.g., <base href="/"> ▪ Import RouterModule and Routes in TypeScript ▪ Create a router configuration ▪ Use tag <router-outlet> to display routed components 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 86
  83. Router Configuration import { Routes } from '@angular/router'; import {UsersComponent}

    from './user/users.component'; import {AboutComponent} from './about/about.component'; export const routerConfig: Routes = [ { path: '', redirectTo: 'users', pathMatch: 'full' }, { path: 'users', component: UsersComponent }, { path: 'about', component: AboutComponent } ]; 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 87
  84. Routing HTML <nav> <ul> <li><a [routerLink]="['about']">About</a></li> <li><a [routerLink]="['users']">Users</a></li> </ul> </nav>

    <router-outlet></router-outlet> 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 88
  85. Angular CLI ▪ Installation: npm install -g @angular/cli ▪ Create

    a new project and run it: ng new <project name> cd <project name> ng serve ▪ Create new component: ng g component <new component> 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 89
  86. Live Demo 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 90
  87. Lab 4: Task 1 ▪ Open terminal in lab4/complete ▪

    Invoke: npm start ▪ builds everything using Angular CLI ▪ Starts a Web server at port 4200 ▪ Open http://localhost:4200 in a web browser ▪ You should see the Angular demo app 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 91
  88. Lab 4: Task 2 ▪ Work in lab4/initial ▪ Read

    the README.adoc ▪ Create your own CLI based Angular app 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 92
  89. Building the Angular App 11/11/2022 © Kai Tödter, Licensed under

    a Creative Commons Attribution 4.0 International License. 93
  90. Angular & TypeScript ▪ Angular is written itself in TypeScript

    ▪ Angular brings its own type definitions ▪ TypeScript is the recommended language to write Angular apps ▪ But you could also use JavaScript or Dart 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 94
  91. Angular App with no Styling 11/11/2022 © Kai Tödter, Licensed

    under a Creative Commons Attribution 4.0 International License. 95
  92. Lab 5: Task 1 ▪ Open terminal in lab5/complete ▪

    Invoke: npm start ▪ builds everything using the Angular CLI ▪ Starts a Web server at port 4200 ▪ Open http://localhost:4200 in a web browser ▪ You should see the web app with no styling ▪ Play around with it 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 96
  93. Lab 5: Task 2 ▪ Work in lab5/initial ▪ Implement

    a small Angular app that displays a list of users and an “About” screen ▪ Add decorators, constructor and method ngOnInit in user.component.ts ▪ Add Angular markup (*ngFor etc.) in user.component.html ▪ Add routing in app.component.html 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 97
  94. Bootstrap ▪ www.getbootstrap.com 11/11/2022 © Kai Tödter, Licensed under a

    Creative Commons Attribution 4.0 International License. 98
  95. Bootstrap Summary ▪ By Twitter ▪ HTML, CSS3, JavaScript ▪

    Templates ▪ Easy to use ▪ Mobile first 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 99
  96. Bootstrap Live Demo 11/11/2022 © Kai Tödter, Licensed under a

    Creative Commons Attribution 4.0 International License. 100
  97. Basic Template 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 101 <!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> <title>Hello, world!</title> </head> <body> <h1>Hello, world!</h1> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
  98. app.component.html <header> <nav class="navbar navbar-dark bg-dark navbar-expand-lg"> <div class="container"> <a

    class="navbar-brand" href="#">Webapp Tutorial</a> <div class="collapse navbar-collapse" id="navbarNavAltMarkup"> <div class="navbar-nav"> <a class="nav-item nav-link" [routerLink]="['users']">Users</a> <a class="nav-item nav-link" [routerLink]="['about']">About</a> </div> </div> </div> </nav> </header> <router-outlet></router-outlet> 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 102
  99. user.component.html <div class="container"> <h4>Users</h4> <table class="table table-striped table-sm"> … 11/11/2022

    © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 103
  100. Bootstrapped Tutorial Web App 11/11/2022 © Kai Tödter, Licensed under

    a Creative Commons Attribution 4.0 International License. 104
  101. Lab 6: Task 1 ▪ Open terminal in lab6/complete ▪

    Invoke: npm start ▪ builds everything using the Angular CLI ▪ Starts a Web server at port 4200 ▪ Open http://localhost:4200 in a web browser ▪ You should see the web app with Bootstrap styling ▪ Play around with it 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 105
  102. Lab 6: Task 2 ▪ Work in lab6/initial ▪ Enhance

    index.html ▪ Use slate.css for a dark Bootstrap theme ▪ Add bootstrap css classes to ▪ app.component.html ▪ user.component.html ▪ about.component.html 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 106
  103. 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 107 Putting it all together
  104. Cross-Origin Resource Sharing (CORS) From Wikipedia: Cross-origin resource sharing (CORS)

    is a mechanism that enables many resources (e.g. fonts, JavaScript, etc.) on a web page to be requested from another domain outside the domain from which the resource originated.[ 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 108
  105. CORS with Angular CLI ▪ Provide a file proxy.conf.json {

    "/api": { "target": "http://localhost:8080", "secure": false } } ▪ Change npm start script: "start": "ng serve --proxy-config proxy.conf.json", 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 109
  106. Angular HTTP ▪ The HTTP service uses Observables from rxjs

    ▪ The user service now makes an asynchronous call to the REST backend and returns an Observable ▪ The user component subscribes for changes and updates its own view model 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 110
  107. User Service with HTTP @Injectable() export class UsersService { constructor(private

    http: HttpClient) {} public getUsers(): Observable<User[]> { const uri = '/api/users'; return this.http.get(uri).pipe( map((response: any) => response._embedded['users']), catchError(this.handleError)); } … 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 111
  108. UsersComponent with Subscription export class UsersComponent { private users: User[];

    constructor(private usersService: UsersService) {} ngOnInit() { this.usersService.getUsers() .subscribe( (users: User[]) => this.users = users, error => console.error( 'UsersComponent: cannot get users')); } } 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 112
  109. Live Demo 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 113
  110. Lab 7: Task 1 ▪ Start the Spring Boot app

    from lab7 ▪ Open terminal in lab7/complete ▪ Invoke: npm start ▪ builds everything using the Angular CLI ▪ Starts a Web server at port 4200 ▪ Open http://localhost:4200 in a web browser ▪ You should see the web app ▪ The user list is served by the backend service 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 114
  111. Lab 7: Task 2 ▪ Implement the user service using

    HTTP ▪ Implement the users component with subscription 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 115
  112. Final Application 11/11/2022 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 116
  113. License ▪ This work is licensed under a Creative Commons

    Attribution 4.0 International License. ▪ See http://creativecommons.org/licenses/by/4.0/ 11/11/2022 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 119