Heim > Artikel > Backend-Entwicklung > Erstellen einer Angular CRUD-App mit einer Go-API
CRUD-Operationen (Erstellen, Lesen, Aktualisieren, Löschen) sind das Rückgrat der meisten Webanwendungen. In diesem Tutorial zeigen wir Ihnen, wie Sie eine CRUD-App mit Angular im Frontend und einer GoAPI im Backend erstellen, was zu einer vollständig integrierten und effizienten Full-Stack-Lösung führt.
Installieren Sie Angular 18 und erstellen Sie ein neues Projekt mit dem folgenden Befehl.
npm install -g @angular/cli@18.0.0 ng new view --minimal --routing --style css --no-standalone --ssr=false
└─ src ├─ app │ ├─ app-routing.module.ts │ ├─ app.component.ts │ ├─ app.interceptor.ts │ ├─ app.module.ts │ └─ components │ └─ product │ ├─ Create.component.ts │ ├─ Delete.component.ts │ ├─ Detail.component.ts │ ├─ Edit.component.ts │ ├─ Index.component.ts │ └─ Product.service.ts ├─ index.html ├─ main.ts └─ styles.css
*In dieser Projektstruktur werden nur die Dateien und Ordner angezeigt, die wir erstellen oder ändern möchten.
import { enableProdMode } from '@angular/core' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { AppModule } from './app/app.module' platformBrowserDynamic().bootstrapModule(AppModule).catch(e => console.error(e))
Diese main.ts-Datei initialisiert eine Angular-Anwendung durch Bootstrapping des AppModule mithilfe der platformBrowserDynamic-Funktion. Es richtet die Anwendung für die Ausführung im Browser ein und behandelt alle Fehler, die während des Bootstrapping-Vorgangs auftreten.
import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from '@angular/forms' import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http' import { AppRoutingModule } from './app-routing.module' import { AppComponent } from './app.component' import { AppInterceptor } from './app.interceptor' import { ProductIndex } from './components/product/Index.component' import { ProductCreate } from './components/product/Create.component' import { ProductDetail } from './components/product/Detail.component' import { ProductEdit } from './components/product/Edit.component' import { ProductDelete } from './components/product/Delete.component' @NgModule({ declarations: [ AppComponent, ProductIndex, ProductCreate, ProductDetail, ProductEdit, ProductDelete, ], imports: [ BrowserModule, AppRoutingModule, FormsModule, HttpClientModule ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AppInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }
Das AppModule ist das Hauptmodul einer Angular-Anwendung. Es importiert Angular-Kernmodule und richtet das Routing mit AppRoutingModule ein. Das Modul deklariert verschiedene produktbezogene Komponenten. Außerdem wird AppInterceptor als HTTP-Interceptor registriert. Die AppComponent wird als Bootstrap-Komponente festgelegt und ist somit der Einstiegspunkt der Anwendung.
import { Component } from '@angular/core' @Component({ selector: 'app-root', template: `<router-outlet></router-outlet>` }) export class AppComponent { }
Die Datei app.component.ts definiert die Stammkomponente AppComponent, die das
import { Injectable } from '@angular/core'; import { HttpInterceptor } from '@angular/common/http'; import { HttpRequest, HttpErrorResponse } from '@angular/common/http' import { Observable, throwError } from 'rxjs' import { HttpHandler } from '@angular/common/http' import { HttpEvent } from '@angular/common/http' @Injectable({ providedIn: 'root' }) export class AppInterceptor implements HttpInterceptor { baseURL = 'http://localhost:8080/api' intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request.clone({ url: this.baseURL + request.url, })) } }
Die AppInterceptor-Klasse ist ein Angular-HTTP-Interceptor, der eine konfigurierbare Basis-URL an alle ausgehenden HTTP-Anforderungs-URLs anhängt, bevor sie an den Server gesendet werden. Dadurch kann die Anwendung den Basis-API-Endpunkt zentralisieren und einfach verwalten.
import { NgModule } from '@angular/core' import { RouterModule, Routes } from '@angular/router' import { ProductIndex } from './components/product/Index.component' import { ProductCreate } from './components/product/Create.component' import { ProductDetail } from './components/product/Detail.component' import { ProductEdit } from './components/product/Edit.component' import { ProductDelete } from './components/product/Delete.component' const routes: Routes = [ { path: '', redirectTo: 'product', pathMatch: 'full' }, { path: 'product', component: ProductIndex }, { path: 'product/create', component: ProductCreate }, { path: 'product/:id', component: ProductDetail }, { path: 'product/edit/:id', component: ProductEdit }, { path: 'product/delete/:id', component: ProductDelete } ] @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Das AppRoutingModule richtet das Routing für eine Angular-Anwendung ein, einschließlich produktbezogener Pfade zum Auflisten, Erstellen, Anzeigen, Bearbeiten und Löschen von Produkten. Es enthält auch eine Route, die vom Stammpfad „/“ zur Produktlistenseite „/product“ weiterleitet.
import { Component } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { ProductService } from './Product.service' @Component({ selector: 'product-create', template: ` <div class="container"> <div class="row"> <div class="col"> <form ngNativeValidate method="post" (submit)="create()"> <div class="row"> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_name">Name</label> <input id="product_name" name="name" class="form-control" [(ngModel)]="product.Name" maxlength="50" /> <span *ngIf="errors.name" class="text-danger">{{errors.name}}</span> </div> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_price">Price</label> <input id="product_price" name="price" class="form-control" [(ngModel)]="product.Price" type="number" /> <span *ngIf="errors.price" class="text-danger">{{errors.price}}</span> </div> <div class="col-12"> <a class="btn btn-secondary" routerLink="/product">Cancel</a> <button class="btn btn-primary">Submit</button> </div> </div> </form> </div> </div> </div>` }) export class ProductCreate { product?: any = {} errors?: any = {} constructor(private router: Router, private route: ActivatedRoute, private ProductService: ProductService) { } create() { this.ProductService.create(this.product).subscribe(() => { this.router.navigateByUrl('/product') }, (e) => { alert(e.error) }) } }
Die ProductCreate-Komponente stellt ein Formular zum Erstellen eines neuen Produkts bereit und bindet Eingabefelder für Name und Preis an ein Produktobjekt. Bei der Übermittlung ruft es ProductService auf, um das Produkt zu erstellen, und navigiert zurück zur Produktliste. Validierungsfehler werden neben den entsprechenden Feldern angezeigt und alle Erstellungsfehler lösen eine Warnung aus.
npm install -g @angular/cli@18.0.0 ng new view --minimal --routing --style css --no-standalone --ssr=false
Die ProductDelete-Komponente in Delete.component.ts ist eine Angular-Komponente, die das Löschen eines Produkts übernimmt. Es wird ein Formular mit schreibgeschützten Feldern angezeigt, in denen die Produktdetails (ID, Name und Preis) angezeigt werden. Wenn die Komponente initialisiert wird, ruft sie die Produktdetails mithilfe der Produkt-ID aus der Route ab. Bei der Formularübermittlung ruft die Methode delete() ProductService auf, um das Produkt zu löschen, und leitet dann zur Produktliste weiter. Wenn beim Löschen ein Fehler auftritt, wird eine Warnung angezeigt.
└─ src ├─ app │ ├─ app-routing.module.ts │ ├─ app.component.ts │ ├─ app.interceptor.ts │ ├─ app.module.ts │ └─ components │ └─ product │ ├─ Create.component.ts │ ├─ Delete.component.ts │ ├─ Detail.component.ts │ ├─ Edit.component.ts │ ├─ Index.component.ts │ └─ Product.service.ts ├─ index.html ├─ main.ts └─ styles.css
Die ProductDetail-Komponente zeigt die Details eines bestimmten Produkts an. Es ruft die Produktinformationen basierend auf der ID aus der Route ab und zeigt die ID, den Namen und den Preis des Produkts in schreibgeschützten Feldern an. Zur Navigation stellt die Komponente die Schaltflächen „Zurück“ und „Bearbeiten“ zur Verfügung. Die Produktdetails werden abgerufen und angezeigt, wenn die Komponente initialisiert wird.
import { enableProdMode } from '@angular/core' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { AppModule } from './app/app.module' platformBrowserDynamic().bootstrapModule(AppModule).catch(e => console.error(e))
Mit der ProductEdit-Komponente können Benutzer ein vorhandenes Produkt bearbeiten. Es ruft die Produktdetails anhand der Produkt-ID aus der Route ab und zeigt sie in einem Formular mit editierbaren Feldern für Name und Preis an. Beim Absenden des Formulars wird das Produkt über ProductService aktualisiert und zurück zur Produktliste navigiert. Alle Fehler beim Abrufen oder Aktualisieren werden als Warnungen angezeigt und Validierungsfehler werden neben den relevanten Feldern angezeigt.
import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from '@angular/forms' import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http' import { AppRoutingModule } from './app-routing.module' import { AppComponent } from './app.component' import { AppInterceptor } from './app.interceptor' import { ProductIndex } from './components/product/Index.component' import { ProductCreate } from './components/product/Create.component' import { ProductDetail } from './components/product/Detail.component' import { ProductEdit } from './components/product/Edit.component' import { ProductDelete } from './components/product/Delete.component' @NgModule({ declarations: [ AppComponent, ProductIndex, ProductCreate, ProductDetail, ProductEdit, ProductDelete, ], imports: [ BrowserModule, AppRoutingModule, FormsModule, HttpClientModule ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AppInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }
Die ProductIndex-Komponente zeigt eine Liste von Produkten in einem Tabellenformat an. Es ruft bei der Initialisierung die Liste der Produkte von ProductService ab und zeigt die ID, den Namen und den Preis jedes Produkts sowie Aktionsschaltflächen zum Anzeigen, Bearbeiten und Löschen jedes Produkts an. Es enthält auch eine Schaltfläche zum Navigieren zur Produkterstellungsseite.
import { Component } from '@angular/core' @Component({ selector: 'app-root', template: `<router-outlet></router-outlet>` }) export class AppComponent { }
Der ProductService verwendet den HttpClient von Angular, um die relevanten HTTP-Anfragen für die Produktverwaltung auszuführen. Es bietet Methoden für:
import { Injectable } from '@angular/core'; import { HttpInterceptor } from '@angular/common/http'; import { HttpRequest, HttpErrorResponse } from '@angular/common/http' import { Observable, throwError } from 'rxjs' import { HttpHandler } from '@angular/common/http' import { HttpEvent } from '@angular/common/http' @Injectable({ providedIn: 'root' }) export class AppInterceptor implements HttpInterceptor { baseURL = 'http://localhost:8080/api' intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request.clone({ url: this.baseURL + request.url, })) } }
Das CSS passt das Layout an, indem es Platz über dem Container hinzufügt und die Schaltflächen horizontal verteilt.
import { NgModule } from '@angular/core' import { RouterModule, Routes } from '@angular/router' import { ProductIndex } from './components/product/Index.component' import { ProductCreate } from './components/product/Create.component' import { ProductDetail } from './components/product/Detail.component' import { ProductEdit } from './components/product/Edit.component' import { ProductDelete } from './components/product/Delete.component' const routes: Routes = [ { path: '', redirectTo: 'product', pathMatch: 'full' }, { path: 'product', component: ProductIndex }, { path: 'product/create', component: ProductCreate }, { path: 'product/:id', component: ProductDetail }, { path: 'product/edit/:id', component: ProductEdit }, { path: 'product/delete/:id', component: ProductDelete } ] @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Der HTML-Code dient als Haupteinstiegspunkt für eine Angular-Anwendung, einschließlich Bootstrap für das Styling, Font Awesome für Symbole und
npm install -g @angular/cli@18.0.0 ng new view --minimal --routing --style css --no-standalone --ssr=false
Erstellen Sie eine Testdatenbank mit dem Namen „example“ und führen Sie die Datei „database.sql“ aus, um die Tabelle und die Daten zu importieren.
└─ src ├─ app │ ├─ app-routing.module.ts │ ├─ app.component.ts │ ├─ app.interceptor.ts │ ├─ app.module.ts │ └─ components │ └─ product │ ├─ Create.component.ts │ ├─ Delete.component.ts │ ├─ Detail.component.ts │ ├─ Edit.component.ts │ ├─ Index.component.ts │ └─ Product.service.ts ├─ index.html ├─ main.ts └─ styles.css
import { enableProdMode } from '@angular/core' import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' import { AppModule } from './app/app.module' platformBrowserDynamic().bootstrapModule(AppModule).catch(e => console.error(e))
Diese Datei enthält die Konfigurationsdetails für die Verbindung zur Datenbank.
import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from '@angular/forms' import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http' import { AppRoutingModule } from './app-routing.module' import { AppComponent } from './app.component' import { AppInterceptor } from './app.interceptor' import { ProductIndex } from './components/product/Index.component' import { ProductCreate } from './components/product/Create.component' import { ProductDetail } from './components/product/Detail.component' import { ProductEdit } from './components/product/Edit.component' import { ProductDelete } from './components/product/Delete.component' @NgModule({ declarations: [ AppComponent, ProductIndex, ProductCreate, ProductDetail, ProductEdit, ProductDelete, ], imports: [ BrowserModule, AppRoutingModule, FormsModule, HttpClientModule ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AppInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }
Diese db.go-Datei konfiguriert die Datenbankverbindung mit GORM. Die SetupDatabase-Funktion lädt Umgebungsvariablen, erstellt eine MySQL-Verbindungszeichenfolge und initialisiert eine GORM-Instanz, die in der globalen DB-Variablen gespeichert wird.
import { Component } from '@angular/core' @Component({ selector: 'app-root', template: `<router-outlet></router-outlet>` }) export class AppComponent { }
Diese router.go-Datei richtet das Routing für eine Go-Anwendung mithilfe des Gin-Frameworks ein. Die SetupRouter-Funktion initialisiert einen Gin-Router mit CORS-Middleware, um alle Ursprünge zuzulassen. Es definiert Routen für die Verarbeitung produktbezogener Vorgänge unter dem Pfad /api/products, die jeweils einer Methode im ProductController zugeordnet sind. Schließlich wird der Gin-Server gestartet.
import { Injectable } from '@angular/core'; import { HttpInterceptor } from '@angular/common/http'; import { HttpRequest, HttpErrorResponse } from '@angular/common/http' import { Observable, throwError } from 'rxjs' import { HttpHandler } from '@angular/common/http' import { HttpEvent } from '@angular/common/http' @Injectable({ providedIn: 'root' }) export class AppInterceptor implements HttpInterceptor { baseURL = 'http://localhost:8080/api' intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request.clone({ url: this.baseURL + request.url, })) } }
Diese Datei „product.go“ definiert ein Produktmodell zur Verwendung mit GORM. Es gibt eine Produktstruktur mit drei Feldern an: Id (ein automatisch inkrementierender Primärschlüssel), Name, Preis.
import { NgModule } from '@angular/core' import { RouterModule, Routes } from '@angular/router' import { ProductIndex } from './components/product/Index.component' import { ProductCreate } from './components/product/Create.component' import { ProductDetail } from './components/product/Detail.component' import { ProductEdit } from './components/product/Edit.component' import { ProductDelete } from './components/product/Delete.component' const routes: Routes = [ { path: '', redirectTo: 'product', pathMatch: 'full' }, { path: 'product', component: ProductIndex }, { path: 'product/create', component: ProductCreate }, { path: 'product/:id', component: ProductDetail }, { path: 'product/edit/:id', component: ProductEdit }, { path: 'product/delete/:id', component: ProductDelete } ] @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Die Datei „product_controller.go“ definiert eine ProductController-Struktur mit Methoden zur Verarbeitung von CRUD-Vorgängen für Produkte in einer Go-Anwendung mithilfe des Gin-Frameworks.
import { Component } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { ProductService } from './Product.service' @Component({ selector: 'product-create', template: ` <div class="container"> <div class="row"> <div class="col"> <form ngNativeValidate method="post" (submit)="create()"> <div class="row"> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_name">Name</label> <input id="product_name" name="name" class="form-control" [(ngModel)]="product.Name" maxlength="50" /> <span *ngIf="errors.name" class="text-danger">{{errors.name}}</span> </div> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_price">Price</label> <input id="product_price" name="price" class="form-control" [(ngModel)]="product.Price" type="number" /> <span *ngIf="errors.price" class="text-danger">{{errors.price}}</span> </div> <div class="col-12"> <a class="btn btn-secondary" routerLink="/product">Cancel</a> <button class="btn btn-primary">Submit</button> </div> </div> </form> </div> </div> </div>` }) export class ProductCreate { product?: any = {} errors?: any = {} constructor(private router: Router, private route: ActivatedRoute, private ProductService: ProductService) { } create() { this.ProductService.create(this.product).subscribe(() => { this.router.navigateByUrl('/product') }, (e) => { alert(e.error) }) } }
Diese main.go-Datei ist der Einstiegspunkt für die Go-Anwendung. Es importiert Konfigurations- und Routingpakete und ruft dann config.SetupDatabase() auf, um die Datenbankverbindung zu initialisieren, und router.SetupRouter(), um die Routen der Anwendung einzurichten.
Angular-Projekt ausführen
import { Component } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { ProductService } from './Product.service' @Component({ selector: 'product-delete', template: ` <div class="container"> <div class="row"> <div class="col"> <form ngNativeValidate method="post" (submit)="this.delete()"> <div class="row"> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_id">Id</label> <input readonly id="product_id" name="id" class="form-control" value="{{product.Id}}" type="number" required /> </div> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_name">Name</label> <input readonly id="product_name" name="name" class="form-control" value="{{product.Name}}" maxlength="50" /> </div> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_price">Price</label> <input readonly id="product_price" name="price" class="form-control" value="{{product.Price}}" type="number" /> </div> <div class="col-12"> <a class="btn btn-secondary" routerLink="/product">Cancel</a> <button class="btn btn-danger">Delete</button> </div> </div> </form> </div> </div> </div>` }) export class ProductDelete { product?: any = {} constructor(private router: Router, private route: ActivatedRoute, private ProductService: ProductService) { } ngOnInit() { this.get() } get() { return this.ProductService.delete(this.route.snapshot.params['id']).subscribe(data => { this.product = data }, e => { alert(e.error) }) } delete() { this.ProductService.delete(this.route.snapshot.params['id'], this.product).subscribe(() => { this.router.navigateByUrl('/product') }, (e) => { alert(e.error) }) } }
Go API-Projekt ausführen
import { Component } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { ProductService } from './Product.service' @Component({ selector: 'product-detail', template: ` <div class="container"> <div class="row"> <div class="col"> <form ngNativeValidate method="post"> <div class="row"> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_id">Id</label> <input readonly id="product_id" name="id" class="form-control" value="{{product.Id}}" type="number" required /> </div> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_name">Name</label> <input readonly id="product_name" name="name" class="form-control" value="{{product.Name}}" maxlength="50" /> </div> <div class="mb-3 col-md-6 col-lg-4"> <label class="form-label" for="product_price">Price</label> <input readonly id="product_price" name="price" class="form-control" value="{{product.Price}}" type="number" /> </div> <div class="col-12"> <a class="btn btn-secondary" routerLink="/product">Back</a> <a class="btn btn-primary" routerLink="/product/edit/{{product.Id}}">Edit</a> </div> </div> </form> </div> </div> </div>` }) export class ProductDetail { product?: any = {} constructor(private route: ActivatedRoute, private ProductService: ProductService) { } ngOnInit() { this.get() } get() { return this.ProductService.get(this.route.snapshot.params['id']).subscribe(data => { this.product = data }, e => { alert(e.error) }) } }
Öffnen Sie den Webbrowser und gehen Sie zu http://localhost:4200
Sie finden diese Produktlistenseite.
Klicken Sie auf die Schaltfläche „Anzeigen“, um die Produktdetailseite anzuzeigen.
Klicken Sie auf die Schaltfläche „Bearbeiten“, um das Produkt zu ändern und seine Details zu aktualisieren.
Klicken Sie auf die Schaltfläche „Senden“, um die aktualisierten Produktdetails zu speichern.
Klicken Sie auf die Schaltfläche „Erstellen“, um ein neues Produkt hinzuzufügen und seine Details einzugeben.
Klicken Sie auf die Schaltfläche „Senden“, um das neue Produkt zu speichern.
Klicken Sie auf die Schaltfläche „Löschen“, um das zuvor erstellte Produkt zu entfernen.
Klicken Sie auf die Schaltfläche „Löschen“, um die Entfernung dieses Produkts zu bestätigen.
Abschließend haben wir gelernt, wie man ein einfaches Angular-Projekt mit Komponenten, Ansichten und Routing erstellt und gleichzeitig eine API mit dem Gin-Framework als Backend einrichtet. Durch den Einsatz von GORM für Datenbankoperationen ist es uns gelungen, ein dynamisches Front-End zu entwickeln, das sich nahtlos in ein leistungsstarkes und effizientes Backend integriert. Diese Kombination bildet eine solide Grundlage für die Entwicklung moderner Full-Stack-Webanwendungen.
Quellcode: https://github.com/stackpuz/Example-CRUD-Angular-18-Go
Erstellen Sie in wenigen Minuten eine Angular CRUD-App: https://stackpuz.com
Das obige ist der detaillierte Inhalt vonErstellen einer Angular CRUD-App mit einer Go-API. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!