-
Notifications
You must be signed in to change notification settings - Fork 0
Frontend Angular en
- Download Node.js. Download and installation from:
https://nodejs.org/en/
- npm - Package Manager (is available after the installation of node on the command line)
-
Angular/cli. Installation from command line:
npm install -g @angular/cli
-
Json-server. From command line:
npm install -g json-server
-
IDE's, that work with Angular:
Visual Studio Code
Atom
Webstorm
ng new test-app
cd test-app
ng serve
-
The Angular client is a practical tool to create new components, services etc. easily.
-
You can install the Angular client globally on the computer with:
-
npm install -g @angular/cli
-
These are some examples for the most important classes in Angular:
-
Create a service
ng generate service hospital
-
Create a component
ng generate component hospital
-
Create a model
ng generate class hospital --type=model
-
Create a module
ng genarate module hospital
- This documentation shows a good overview:
https://angular.io/docs
The basic blocks of an Angular application are the NgModules, which contain the complication context for the components. The NgModules merge related code into functional sets. The complete application is then a combination of NgModules. Every Angular application has at least one module, the root module, which enables bootstrapping. Typically there are many more modules available.
- In spite we don't have a lot of different components and services we just need the app-module and didn't create more modules. But we have also predefined modules, which we use in the project.
- Our app-module is set up like this:
import {environment} from "../environments/environment";
import {HttpClientModule} from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ApplicationRef } from '@angular/core';
import { FormsModule} from '@angular/forms';
import { CommonModule } from '@angular/common';
import {AppRoutingModule} from "./app-routing.module";
import { AppComponent } from './app.component';
import { MapsComponent } from './components/maps/maps.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { HospitalComponent } from './components/hospital/hospital.component';
import { DropdownComponent } from './components/dropdown/dropdown.component';
import { CharacteristicsComponent } from './components/characteristics/characteristics.component';
import {CharacteristicsService} from './services/characteristics.service';
import {HospitalService} from "./services/hospital.service";
@NgModule({
declarations: [
AppComponent,
MapsComponent,
NavbarComponent,
HospitalComponent,
DropdownComponent,
CharacteristicsComponent
],
imports: [
BrowserModule,
HttpClientModule,
CommonModule,
FormsModule,
AppRoutingModule,
],
providers: [
CharacteristicsService,
HospitalService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
- The data is loaded with services and is used after that in the associated components
- The services are used to provide program logic that is used in different components
- All the logic that is not in direct context with the view is outsourced in services
- To retrieve the data in the service from the backend, the HttpClient is used, which accesses the desired URL's, where the JSONs are located
import { HttpClient, HttpHeaders } from '@angular/common/http';
constructor(private http: HttpClient) {
}
- In the hospital services we get the hospitals with all corresponding data (addresses, coordinates, attributes)
/**
* Gets all hospitals with all corresponding data (address, coordinates, attributes)
* @returns {Observable<Hospital[]>} data in form of the defined model Hospital
*/
getAll(): Observable<Hospital[]> {
return this.http.get<Hospital[]>('https://geopital.herokuapp.com/' + 'api/hospitals')
.map(res => {
return res as Hospital[]
})
}
- In the characteristics service we load the numeric and the categorical attributes separated, to use them for the attribute selection
- The numerical attributes determine the size of the points
- The categorical attribues determine the shape
- Further processing is happening in the dropdown component
/**
* Gets all attributes which a hospital can have
* @returns {Observable<Attributes[]>} data in form of the defined model Attributes
*/
getCategoricalAttributes(): Observable<Attributes[]> {
return this.http.get<Attributes[]>('https://geopital.herokuapp.com/' + 'api/attributeTypes')
.map(res => {
return res['attribute_types_string'] as Attributes[];
})
}
getNumericalAttributes(): Observable<Attributes[]> {
return this.http.get<Attributes[]>('https://geopital.herokuapp.com/' + 'api/attributeTypes')
.map(res => {
return res['attribute_types_number'] as Attributes[];
})
}
- In the components we have all logic implemented, which is in direct context to the view
- A component includes a typescript, a HTML and a CSS file
- TypeScript: For the logic
- HTML: For the view
- CSS: For the design
- The dropdown component is the middle part of the menu on the right side
- Im Dropdown Component werden die numerischen und kategoriellen Variablen weiterverarbeitet und in das Auswählfeld auf der rechten Seite des Bildschirmes geladen
/**
* Is called on init and loads the attribute-array from the backend.
* The attributes are stored in two arrays, one that contains all the
* numerical and the other that contains all categorical attributes
* The attributes are then displayed in the html.
*/
ngOnInit() {
this.hospitalService.getCategoricalAttributes()
.subscribe(attributes => {
this.categoricalAttributes = attributes;
});
this.hospitalService.getNumericalAttributes()
.subscribe(attributes => {
this.numericalAttributes = attributes;
});
}
- Im HTML werden dann die Daten auf diese Weise geladen (Beispiel für die kategoriellen Attribute
<!-- first dropdown with categorical attributes -->
<div id="numAttr" class="dropdown" style="padding:5px;">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
1. Attribut:
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" *ngFor="let attribute of categoricalAttributes"
(click)="selectedNumAttribute(attribute)">{{ attribute.nameDE }}</a>
</div>
</div>
- Der Navbarkomponent ist der oberste Teil des Menus auf der rechten Seite
- Hier können die Spitaltypen ausgewählt werden
- Diese Navbar fungiert gleichzeitig als Legende, welche Farbe für welchen Spitaltyp gilt
- Das folgende Beispiel zeigt den Code für die Auswahl des Universitätsspital (die weitere Logik geschieht im MapInitializer, Dokumentation für d3)
/** NavbarComponent.ts */
if (hospitalType == 'K111') {
this.numUniSp = this.numUniSp+1;
updateMap(this.numUniSp, this.numZentSp, this.numGrundVers, this.numPsychKl, this.numRehaKl, this.numSpezKl);
}
<!-- NavbarComponent.html -->
<label class="container">Universitätsspitäler
<input type="checkbox" checked="checked" (change)="selectHospitalType('K111')">
<span class="checkmark1"></span>
</label>
/* NavbarComponent.css */
.checkmark1 {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
background-color:#a82a2a;
}
- Im Map Component wird die getAll() Funktion des Hospital Servies aufgerufen um die Spitäler mit allen Attributen zu laden
- Zusätzlich werden aus dem Characteristics Service die numerischen Attribute geladen um die Grösse der Punkte auf der Karte zu bestimmen. Als Default Wert nehmen wir den Ertrag aus medizinischen Leistungen der jeweiligen Spitäler
/**
* Loads all hospital data from backend with the help of hospitalService
* and the Characteristics Service (for the attributes) and gives
* it to the mapDrawer() and setNumAttributes() functions in mapInitializer.js
*/
ngOnInit() {
this.characteristicsService.getNumericalAttributes()
.subscribe(attributes => {
this.numericalAttributes = attributes;
for (let i of this.numericalAttributes) {
if(this.numericalAttributes.code!=null){
if(this.numericalAttributes[i].code=="EtMedL"){
setNumAttribute(this.numericalAttributes[i]);
}
}
}
});
this.hospitalService.getAll()
.subscribe(hospitals => {
this.hospitalsList = hospitals;
mapDrawer(this.hospitalsList);
});
}
- Im MapComponent.html wird die Karte initialisiert, welche im MapInitializer.js erstellt wird
<!-- show map defined in mapInitializer.js on screen -->
<div id="mapid" style="width: 100%; height: 100%; position: absolute"></div>
- Zusätzlich werden im MapComponent.html noch alle Components aufgerufen, welche danach auf der Karte angezeigt werden
<!-- shows navbar on the map -->
<app-navbar></app-navbar>
<!-- shows dropdown on the map -->
<app-dropdown></app-dropdown>
<!-- shows the characteristics on the map -->
<app-characteristics></app-characteristics>
- Der Visualisierungs Teil wird in der Frontend D3 Dokumentation erläutert
Ohne Dokumentation wären wir alle Tiere.