Fermer

novembre 29, 2018

Construire une application CRUD de base avec Angular et Node –


Cet article a été publié à l'origine sur sur le blog des développeurs d'Okta . Merci de soutenir les partenaires qui rendent SitePoint possible.

Ces dernières années, les applications de page unique (SPA) sont devenues de plus en plus populaires. Un SPA est un site Web composé d'une seule page. Cette page unique sert de conteneur pour une application JavaScript. Le JavaScript est responsable de l’obtention du contenu et de son rendu dans le conteneur. Le contenu est généralement obtenu à partir d'un service Web et les API RESTful sont devenues le choix idéal dans de nombreuses situations. La partie de l'application qui constitue la SPA est communément appelée client ou front-end tandis que la partie responsable de l'API REST est appelée serveur . ] ou le back-end . Dans ce didacticiel, vous allez développer une application simple page angulaire avec un backend REST, basée sur Node et Express.

Vous utiliserez Angular car elle suit le modèle MVC et sépare proprement la vue des modèles. Il est simple de créer des modèles HTML qui sont remplis de manière dynamique avec des données et mis à jour automatiquement chaque fois que les données sont modifiées. J'ai appris à aimer ce framework parce qu'il est très puissant, qu'il possède une énorme communauté et une excellente documentation.

Pour le serveur, vous utiliserez Node avec Express. Express est une structure qui facilite la création d'API REST en permettant de définir du code qui s'exécute pour différentes requêtes sur le serveur. Des services supplémentaires peuvent être connectés globalement ou en fonction de la demande. Un certain nombre de frameworks reposent sur Express et automatisent la transformation de vos modèles de base de données en une API. Ce didacticiel n'utilisera aucun de ces éléments pour rester concentré.

Angular encourage l'utilisation de TypeScript. TypeScript ajoute des informations de frappe à JavaScript et, à mon avis, constitue l’avenir du développement d’applications à grande échelle en JavaScript. Pour cette raison, vous allez développer le client et le serveur à l'aide de TypeScript.

Voici les bibliothèques que vous utiliserez pour le client et le serveur:

  • Angular: Le cadre utilisé pour créer l'application client.
  • Okta for Authorization: Un plugin qui gère l'autorisation d'authentification unique à l'aide d'Okta, à la fois sur le client et sur le serveur.
  • Matériau angulaire: Un plugin angulaire fournissant des fonctionnalités clés en main. Material Design
  • Node: Le serveur exécutant le code JavaScript
  • Express: Une bibliothèque de routage permettant de répondre aux demandes de serveur et de créer des API REST
  • TypeORM: Une bibliothèque ORM de base de données pour TypeScript

Démarrez votre application client angulaire de base

Commençons par implémenter un client de base en utilisant Angular. L'objectif est de développer un catalogue de produits vous permettant de gérer les produits, leurs prix et leurs niveaux de stock. À la fin de cette section, vous aurez une application simple composée d’une barre supérieure et de deux vues, Maison et Produits. La vue Produits n'aura pas encore de contenu et rien ne sera protégé par mot de passe. Ceci sera couvert dans les sections suivantes:

Pour commencer, vous devrez installer Angular. Je suppose que Node est déjà installé sur votre système et que vous pouvez utiliser la commande npm . Tapez la commande suivante dans un terminal:

 npm install -g @ angular / cli @ 7.0.2

Selon votre système, vous devrez peut-être exécuter cette commande à l'aide de sudo car il installera le paquet globalement. Le package angular-cli fournit la commande ng utilisée pour gérer les applications angulaires. Une fois installé, accédez au répertoire de votre choix et créez votre première application Angular à l’aide de la commande suivante:

 ng new MyAngularClient

Si vous utilisez Angular 7, vous obtiendrez deux requêtes. La première vous demande si vous souhaitez inclure le routage. Répondre oui à ceci. La deuxième requête concerne le type de feuilles de style que vous souhaitez utiliser. CSS .

ng new créera un nouveau répertoire appelé MyAngularClient et le remplira d'un squelette d'application. Prenons un peu de temps pour examiner certains des fichiers créés par la commande précédente. Dans le répertoire src de l'application, vous trouverez un fichier index.html qui constitue la page principale de l'application. Il ne contient pas grand chose et joue simplement le rôle d’un conteneur. Vous verrez également un fichier style.css . Celui-ci contient la feuille de style globale appliquée dans toute l'application. Si vous parcourez les dossiers, vous remarquerez peut-être un répertoire src / app contenant cinq fichiers.

 app-routing.module.ts
app.component.css
app.component.html
app.component.ts
app.component.spec.ts
app.module.ts

Ces fichiers définissent le composant principal de l'application qui sera inséré dans le fichier index.html . Voici une brève description de chacun des fichiers: Le fichier

  • app.component.css contient les feuilles de style du composant principal de l'application . Les styles peuvent être définis localement pour chaque composant
  • app.component.html contient le modèle HTML du composant
  • app.component.ts . Le fichier contient le code contrôlant la vue
  • app.module. .ts définit les modules que votre application utilisera
  • app-routing.module.ts est configuré pour définir les itinéraires de votre application
  • app.component.spec.ts contient un Squelette pour les tests unitaires du composant app

Je ne couvrirai pas les tests dans ce didacticiel, mais dans les applications réelles, vous devriez utiliser cette fonctionnalité. Avant de pouvoir commencer, vous devrez installer quelques paquets supplémentaires. Cela vous aidera à créer rapidement une mise en page réactive bien conçue. Naviguez jusqu'au répertoire de base du client, MyAngularClient puis tapez la commande suivante:

 npm i @ angular / material @ 7.0.2 @ angular / cdk @ 7.0.2 @ angular / animations @ 7.0 .1 @ angular / flex-layout @ 7.0.0-beta.19

Les bibliothèques @ angular / material et @ angular / cdk fournissent des composants basés sur le document Material Design de Google, @ angular / animations . et @ angular / flex-layout vous donne les outils pour rendre votre conception sensible.

Créez ensuite le modèle HTML pour le composant app . Ouvrez src / app / app.component.html et remplacez le contenu par le suivant:


  

  
;   

La ​​barre mat-tool contient la barre d'outils de conception de matériau, alors que router-outlet est le conteneur qui sera rempli par le routeur. Le fichier app.component.ts doit être modifié pour contenir les éléments suivants:

 import {Component} from '@ angular / core';

@Composant({
  sélecteur: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
classe d'exportation AppComponent {
  titre public = 'Mon application angulaire';
  public isAuthenticated: boolean;

  constructeur () {
    this.isAuthenticated = false;
  }

  s'identifier() {
  }

  Connectez - Out() {
  }
}

Il s'agit du contrôleur du composant app . Vous pouvez voir qu'il contient une propriété appelée isAuthenticated avec deux méthodes login et logout . Pour le moment, ils ne font rien. Ils seront implémentés dans la section suivante qui traite de l’authentification des utilisateurs avec Okta. Définissez maintenant tous les modules que vous utiliserez. Remplacez le contenu de app.module.ts par le code ci-dessous:

 import {BrowserModule} from '@ angular / platform-browser';
importer {NgModule} de '@ angular / core';
importer {BrowserAnimationsModule} depuis '@ angular / platform-browser / animations';
importer {FlexLayoutModule} depuis '@ angular / flex-layout';
importer {
  MatButtonModule,
  MatDividerModule,
  MatIconModule,
  MatMenuModule,
  MatProgressSpinnerModule,
  MatTableModule,
  MatToolbarModule
} de '@ angular / material';
importer {HttpClientModule} à partir de '@ angular / common / http';
importer {FormsModule} à partir de '@ angular / forms';

import {AppRoutingModule} depuis './app-routing.module';
importer {AppComponent} à partir de './app.component';

@NgModule ({
  déclarations: [
    AppComponent
  ],
  importations: [
    AppRoutingModule,
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    FlexLayoutModule,
    MatToolbarModule,
    MatMenuModule,
    MatIconModule,
    MatButtonModule,
    MatTableModule,
    MatDividerModule,
    MatProgressSpinnerModule,
    FormsModule,
  ],
  fournisseurs: [],
  bootstrap: [AppComponent]
})
classe d'exportation AppModule {}

Remarquez tous les modules de conception de matériaux. La bibliothèque @ angular / material vous oblige à importer un module pour chaque type de composant que vous souhaitez utiliser dans votre application. À partir de Angular 7, le squelette d'application par défaut contient un fichier séparé appelé app-routing.module.ts . Editez ceci pour déclarer les routes suivantes:

 import {NgModule} from '@ angular / core';
importer {Routes, RouterModule} depuis '@ angular / router';
importer {ProductsComponent} de './products/products.component';
importer {HomeComponent} de './home/home.component';

routes const: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'products',
    component: ProductsComponent
  }
];

@NgModule ({
  importations: [RouterModule.forRoot(routes)],
  exportations: [RouterModule]
})
classe d'exportation AppRoutingModule {}

Ceci définit deux routes correspondant au chemin racine et au chemin des produits . Il associe également les composants HomeComponent et Products à ces itinéraires. Créez ces composants maintenant. Dans le répertoire de base du client angulaire, tapez les commandes suivantes:

 en train de générer le composant Products
ng générer un composant

Ceci crée les fichiers html css et spec.ts pour chaque composant. Il met également à jour app.module.ts pour déclarer les nouveaux composants. Ouvrez home.component.html dans le répertoire src / app / home et collez le contenu suivant.

Hello World

Ceci est la page d'accueil de votre application Angular

  

Ajoutez également du style au fichier home.component.css également.

 .hero {
  text-align: center;
  hauteur: 90vh;
  affichage: flex;
  direction de flexion: colonne;
  justifier-contenu: centre;
  famille de polices: sans-serif;
}

Laissez le ProductsComponent vide pour le moment. Cela sera mis en œuvre une fois que vous aurez créé le serveur REST principal et pourrez le remplir avec certaines données. Pour que tout soit beau, il ne reste que deux petites tâches. Copiez les styles suivants dans src / style.css

 @import "~@angular/material/prebuilt-themes/deeppurple-amber.css";

corps {
  marge: 0;
  famille de polices: sans-serif;
}

.expanded-toolbar {
  justifier-contenu: espace-entre;
}

h1 {
  text-align: center;
}

Enfin, pour rendre les icônes de conception de matériau, ajoutez une ligne à l'intérieur des balises du fichier index.html .

  

Vous êtes maintenant prêt à lancer le serveur Angular et à voir ce que vous avez accompli jusqu'à présent. Dans le répertoire de base de l'application client, tapez la commande suivante:

 ng serve

Ouvrez ensuite votre navigateur et accédez à http: // localhost: 4200 .

Ajoutez une authentification à votre nœud et une application angulaire

Si vous avez déjà développé des applications Web à partir de zéro, vous le saurez la quantité de travail nécessaire pour permettre aux utilisateurs de s'inscrire, de vérifier, de se connecter et de se déconnecter de votre application. En utilisant Okta, ce processus peut être grandement simplifié. Pour commencer, vous aurez besoin d’un compte de développeur avec Okta.

 developer.okta.com

Dans votre navigateur, accédez à developer.okta.com et cliquez sur Créez un compte gratuit et entrez vos détails.

 Commencez à construire sur Okta

Une fois que vous avez terminé, vous accédez à votre tableau de bord du développeur. Cliquez sur le bouton Ajouter une application pour créer une nouvelle application.

 Ajouter une application

Commencez par créer une nouvelle application d'une page. Choisissez Application de page unique puis cliquez sur Suivant .

 Créer une nouvelle application de page unique

La page suivante, vous devrez modifier les paramètres par défaut . Assurez-vous que le numéro de port est 4200. Il s’agit du port par défaut pour les applications Angular.

 My Angular App

C’est tout. Vous devriez maintenant voir un ID client que vous devrez coller dans votre code TypeScript.

Pour implémenter l'authentification sur le client, installez la bibliothèque Okta pour Angular.

 npm install @ okta / okta -angular@1.0.7 --save-exact

Dans app.module.ts importez le OktaAuthModule .

 import {OktaAuthModule} de '@ okta / okta-angular';

Dans la liste des importations du module app ajoutez:

 OktaAuthModule.initAuth ({
  émetteur: 'https: // {yourOktaDomain} / oauth2 / default',
  redirectUri: 'http: // localhost: 4200 / implicit / callback',
  clientId: '{YourClientId}'
})

Ici votre domaine OkDomain doit être remplacé par le domaine de développement que vous voyez dans votre navigateur lorsque vous accédez à votre tableau de bord Okta. YourClientId doit être remplacé par l'ID client que vous avez obtenu lors de l'enregistrement de votre application. Le code ci-dessus rend Okta Authentication Module disponible dans votre application. Utilisez-le dans app.component.ts et importez le service.

 import {OktaAuthService} à partir de '@ okta / okta-angular';

Modifiez le constructeur pour injecter le service et vous y abonner.

 constructeur (public oktaAuth: OktaAuthService) {
  this.oktaAuth. $ authenticationState.subscribe (
    (isAuthenticated: boolean) => this.isAuthenticated = isAuthenticated
  )
}

Désormais, toute modification du statut d'authentification sera reflétée dans la propriété isAuthenticated . Vous aurez toujours besoin de l'initialiser lorsque le composant est chargé. Créez une méthode ngOnInit et ajoutez implémente OnInit à votre définition de classe

 import {Component, OnInit} depuis '@ angular / core';
...
La classe d'exportation AppComponent implémente OnInit {
  ...
  async ngOnInit () {
    this.isAuthenticated = attend this.oktaAuth.isAuthenticated ();
  }
}

Enfin, implémentez les méthodes de connexion login et pour déconnecter afin de réagir à l'interface utilisateur et de connecter l'utilisateur sur une session ou la déconnexion.

 login () {
  this.oktaAuth.loginRedirect ();
}

Connectez - Out() {
  this.oktaAuth.logout ('/');
}

Dans le module de routage, vous devez enregistrer la route qui sera utilisée pour la demande de connexion. Ouvrez app-routing.module.ts et importez OktaCallbackComponent et OktaAuthGuard .

 importez {OktaCallbackComponent, OktaAuthGuard} de '@ okta / okta-angular'. ;

Ajoutez une autre route au groupe de routes .

 {
  chemin: 'implicite / rappel',
  composant: OktaCallbackComponent
}

Cela permettra à l'utilisateur de se connecter à l'aide du bouton Login . Pour protéger la route Products des accès non autorisés, ajoutez la ligne suivante à la route .

 {
  chemin: 'produits',
  composant: ProductsComponent,
  canActivate: [OktaAuthGuard]
}

C’est tout. Désormais, lorsqu'un utilisateur tente d'accéder à la vue Produits, il sera redirigé vers la page de connexion Okta. Une fois connecté, l'utilisateur sera redirigé vers la vue Produits.

Implémentation d'une API REST de nœud

L'étape suivante consiste à implémenter un serveur basé sur Node and Express qui stockera les informations sur le produit. Cela utilisera un certain nombre de bibliothèques plus petites pour vous rendre la vie plus facile. Pour développer en TypeScript, vous aurez besoin des polices dactylographiées et tsc . Pour la couche d'abstraction de base de données, vous utiliserez TypeORM . C'est une bibliothèque pratique qui injecte le comportement dans les classes TypeScript et les transforme en modèles de base de données. Créez un nouveau répertoire qui contiendra votre application serveur, puis exécutez la commande suivante:

 npm init

Répondez à toutes les questions, puis exécutez:

 npm install --save-exact express@4.16.4 @ types / express @ 4.16.0 @ okta / jwt-verifier @ 0.0.14 express-bearer-token @ 2.2.0 tsc@1.20150623.0 typescript@3.1.3 typeorm@0.2.8 sqlite3@4.0.3 cors@2.8.4 @ types / cors @ 2.8.4

Je ne couvrirai pas toutes ces bibliothèques en détail, mais vous verrez que @ okta / jwt-verifier est utilisé pour vérifier les jetons Web JSON et les authentifier.

Pour que TypeScript fonctionne , créez un fichier tsconfig.json et collez-y le contenu suivant:

 {
  "compilerOptions": {
    "cible": "es6",
    "module": "commonjs",
    "outDir": "dist",
    "experimentalDecorators": vrai,
    "emitDecoratorMetadata": true
  },
  "inclure": [
    "src/**/*.ts"
  ],
  "exclure": [
    "node_modules"
  ]
}

La ​​première étape de la création du serveur consiste à créer un modèle de base de données pour le produit. L'utilisation de TypeORM est simple. Créez un sous-répertoire src et à l'intérieur de celui-ci créez un fichier model.ts . Collez le contenu suivant:

 import {Entity, PrimaryGeneratedColumn, Column, createConnection, Connection, Repository} de 'typeorm';

@Entité()
classe d'exportation Produit {
  @PrimaryGeneratedColumn ()
  id: numéro;

  @Colonne()
  nom: chaîne;

  @Colonne()
  sku: string;

  @Column ('text')
  description: string;

  @Colonne()
  prix: nombre;

  @Colonne()
  stock: numéro;
}

Les annotations TypeORM transforment la définition de la classe en un modèle de base de données. J'aime le projet TypeORM en raison de sa facilité d'utilisation et de la grande variété de connecteurs de base de données SQL et NoSQL pris en charge. Je vous suggère de consulter la documentation à l'adresse https://github.com/typeorm/typeorm .

Vous devrez également avoir accès à un référentiel de produit. Ajoutez également le texte suivant dans le fichier model.ts :

 let connection: Connection;

export async fonction getProductRepository (): Promise <Référentiel > {
  si (connexion === non définie) {
    connection = wait createConnection ({
      type: 'sqlite',
      base de données: 'myangularapp',
      synchronize: true,
      entités: [
        Product
      ],
    });
  }
  return connection.getRepository (Produit);
}

Notez que cela utilise SQLite pour plus de simplicité. Dans un scénario réel, remplacez-le par un connecteur de base de données de votre choix.

Créez ensuite un fichier appelé product.ts . Ce fichier contient la logique de toutes les routes pour les opérations CRUD sur les produits.

 import {NextFunction, Request, Response, Router} from 'express';
import {getProductRepository, Product} depuis './model';

export const routeur: Router = Router ();

router.get ('/ product', fonction async. (req: Request, res: Response, next: NextFunction) {
  essayer {
    const repository = wait getProductRepository ();
    const allProducts = wait repository.find ();
    res.send (allProducts);
  }
  catch (err) {
    retourne ensuite (err);
  }
});

router.get ('/ product /: id', fonction asynchrone (req: Request, res: Response, next: NextFunction) {
  essayer {
    const repository = wait getProductRepository ();
    const produit = wait repository.find ({id: req.params.id});
    res.send (produit);
  }
  catch (err) {
    retourne ensuite (err);
  }
});

router.post ('/ product', fonction async (req: Request, res: Response, next: NextFunction) {
  essayer {
    const repository = wait getProductRepository ();
    const produit = nouveau produit ();
    product.name = req.body.name;
    product.sku = req.body.sku;
    product.description = req.body.description;
    product.price = Number.parseFloat (req.body.price);
    product.stock = Number.parseInt (req.body.stock);

    const result = wait repository.save (produit);
    res.send (résultat);
  }
  catch (err) {
    retourne ensuite (err);
  }
});

router.post ('/ product /: id', fonction asynchrone (req: Request, res: Response, next: NextFunction) {
  essayer {
    const repository = wait getProductRepository ();
    const product = wait repository.findOne ({id: req.params.id});
    product.name = req.body.name;
    product.sku = req.body.sku;
    product.description = req.body.description;
    product.price = Number.parseFloat (req.body.price);
    product.stock = Number.parseInt (req.body.stock);

    const result = wait repository.save (produit);
    res.send (résultat);
  }
  catch (err) {
    retourne ensuite (err);
  }
});

router.delete ('/ product /: id', fonction asynchrone (req: Request, res: Response, next: NextFunction) {
  essayer {
    const repository = wait getProductRepository ();
    wait repository.delete ({id: req.params.id});
    res.send ('OK');
  }
  catch (err) {
    retourne ensuite (err);
  }
});

Ce fichier est un peu long mais ne contient rien d'étonnant. Les objets du produit sont créés et sauvegardés dans la base de données ou supprimés de celle-ci.

Reprenons notre attention sur l’authentification. Vous voudrez vous assurer que seuls les utilisateurs authentifiés peuvent accéder au service. Créez un fichier appelé auth.ts et collez le texte suivant:

 import {Request, Response, NextFunction} à partir de 'express';

const OktaJwtVerifier = require ('@ okta / jwt-verifier');

const oktaJwtVerifier = new OktaJwtVerifier ({
  clientId: '{YourClientId}',
  émetteur: 'https: // {yourOktaDomain} / oauth2 / default'
});

export async fonction oktaAuth (req: Request, res: Response, next: NextFunction) {
  essayer {
    const token = (req as any) .token;
    si (! jeton) {
      return res.status (401) .send ('Non autorisé');
    }
    const jwt = wait oktaJwtVerifier.verifyAccessToken (jeton);
    req.user = {
      uid: jwt.claims.uid,
      email: jwt.claims.sub
    };
    suivant();
  }
  catch (err) {
    return res.status (401) .send (err.message);
  }
}

Tout comme dans l'application client votre domaine OkDomain doit être remplacé par le domaine de développement et votre YourClientId doit être remplacé par votre ID client d'application. L'instance oktaJwtVerifier prend un jeton JWT et l'authentifie. En cas de succès, l'identifiant et le courrier électronique de l'utilisateur seront stockés dans req.user . Sinon, le serveur répondra avec un code d'état 401. La dernière étape pour terminer le serveur est le point d’entrée principal qui démarre le serveur et enregistre le middleware que vous avez défini jusqu’à présent. Créez un fichier server.ts avec le contenu suivant:

 import * as express from 'express';
importer * en tant que cors de 'cors';
import * en tant que bodyParser à partir de 'body-analyseur';
const bearerToken = require ('express-bearer-token');
importer {router as productRouter} de './product'
importer {oktaAuth} de './auth'

const app = express ()
  .use (cors ())
  .use (bodyParser.json ())
  .use (bearerToken ())
  .use (oktaAuth)
  .use (productRouter);

app.listen (4201, (err) => {
  si (err) {
    retourne console.log (err);
  }

  return console.log ('My Node App écoute sur le port 4201');
});

Pour compiler le TypeScript, exécutez la commande

 npx tsc

Ensuite, si vous souhaitez démarrer le serveur, exécutez simplement:

 node dist / server.js

Terminez votre client angulaire

Maintenant que le serveur est terminé, finissons le client. La première étape consiste à créer une classe contenant les données du produit. Cette classe est similaire à la classe Product dans l'application serveur, mais sans les annotations TypeORM. Il sera contenu dans un fichier appelé produit.ts .

 classe d'exportation Produit {
  id ?: string;
  nom: chaîne;
  sku: string;
  description: string;
  prix: nombre;
  stock: numéro;
}

Enregistrez ce fichier dans le même répertoire que le composant products . Il est préférable d'encapsuler l'accès à l'API REST dans un service séparé. Créez un service Products en exécutant la commande ci-dessous.

 ng générer des produits de service / produits

Ceci créera un fichier appelé product.service.ts dans le répertoire src / app / products . Remplissez-le avec le contenu suivant:

 import {Injectable} from '@ angular / core';
importer {HttpClient} à partir de '@ angular / common / http';
importer {OktaAuthService} à partir de '@ okta / okta-angular';
importer {Produit} de './product';

const baseUrl = 'http: // localhost: 4201';

@Injectable ({
  FourniDans: 'root'
})
classe d'exportation ProductsService {

  constructeur (public oktaAuth: OktaAuthService, http privé: HttpClient) {
  }

  demande asynchrone privée (méthode: chaîne, url: chaîne, data ?: any) {
    Const token = wait this.oktaAuth.getAccessToken ();

    console.log ('request' + JSON.stringify (data));
    const result = this.http.request (méthode, url, {
      corps: données,
      responseType: 'json',
      observez: 'corps',
      en-têtes: {
        Autorisation: `Bearer $ {token}`
      }
    });
    retourne la nouvelle promesse  ((résoudre, rejeter) => {
      result.subscribe (résoudre en tant que tout, rejeter en tant que tout);
    });
  }

  getProducts () {
    return this.request ('get', '$ {baseUrl} / product`);
  }

  getProduct (id: string) {
    return this.request ('get', `$ {baseUrl} / product / $ {id}`);
  }

  createProduct (produit: produit) {
    console.log ('createProduct' + JSON.stringify (produit));
    return this.request ('post', '$ {baseUrl} / product`, produit);
  }

  updateProduct (produit: produit) {
    console.log ('updateProduct' + JSON.stringify (produit));
    return this.request ('post', `$ {baseUrl} / product / $ {product.id}`, produit);
  }

  deleteProduct (id: string) {
    return this.request ('delete', `$ {baseUrl} / product / $ {id}`);
  }
}

Le ProductsService contient une méthode publique pour chaque route de l'API REST. La demande HTTP est encapsulée dans une méthode distincte. Notez que la demande contient toujours un jeton Bearer obtenu à partir de OktaAuthService . Il s'agit du jeton utilisé par le serveur pour authentifier l'utilisateur.

Le ProductsComponent peut maintenant être implémenté. Le code suivant fera l'affaire:

 import {Component, OnInit} à partir de '@ angular / core';
importer {MatTableDataSource} depuis '@ angular / material';
importer {ProductsService} de './products.service';
importer {Produit} de './product';

@Composant({
  sélecteur: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css']
})
La classe d'exportation ProductsComponent implémente OnInit {
  displayColumns: string [] = ['name', 'sku', 'description', 'price', 'stock', 'edit', 'delete'];
  dataSource = new MatTableDataSource  ();

  selectedProduct: Produit = nouveau produit ();
  chargement = faux;

  constructeur (public productService: ProductsService) {
  }

  ngOnInit () {
    this.refresh ();
  }

  async refresh () {
    this.loading = true;
    const data = wait this.productService.getProducts ();
    this.dataSource.data = data;
    this.loading = false;
  }

  async updateProduct () {
    if (this.selectedProduct.id! == non défini) {
      wait this.productService.updateProduct (this.selectedProduct);
    } autre {
      wait this.productService.createProduct (this.selectedProduct);
    }
    this.selectedProduct = nouveau produit ();
    attendez this.refresh ();
  }

  editProduct (produit: produit) {
    this.selectedProduct = produit;
  }

  clearProduct () {
    this.selectedProduct = nouveau produit ();
  }

  async deleteProduct (produit: produit) {
    this.loading = true;
    if (confirmez (`Êtes-vous sûr de vouloir supprimer le produit $ {product.name}. Cela ne peut pas être annulé .`)) {
      this.productService.deleteProduct (product.id);
    }
    attendez this.refresh ();
  }
}

La ​​mise en page, dans products.component.html indiquant que le produit est composé de deux parties. La première partie utilise un composant mat-table pour afficher une liste de produits. La deuxième partie présente un formulaire dans lequel l'utilisateur peut modifier un produit nouveau ou existant.

Inventaire du produit

Nom {{product.name}} SKU {{product.sku} } Description {{produit.description}} Prix {{product.price}} Niveau du stock {{product.stock}} 1 19659142] edit

Produit sélectionné

  
  
       

Enfin, ajoutez un peu de style dans à produits.component.css à la présentation.

 .products {
  rembourrage: 2rem;
}

label, input {
  bloc de visualisation;
}

label {
  marge en bas: 1rem;
}

.chargement {
  position: absolue;
  affichage: flex;
  justifier-contenu: centre;
  align-content: center;
  largeur: 100%;
  hauteur: 100%;
  couleur de fond: rgba (255, 255, 255, 0.8);
}

Lorsque tout est terminé, vous pouvez démarrer le client et le serveur et tester votre application. Juste pour répéter, dans le répertoire contenant le serveur, exécutez:

 node dist / server.js

Et dans le répertoire client, exécutez:

 ng serve

Votre application devrait ressembler un peu au suivant

 Inventaire des produits

En savoir plus sur Angular, Node et Express

Dans ce tutoriel, je vous ai guidé tout au long du développement d'une page Web. application utilisant Angular et Node. En utilisant seulement quelques lignes de code, vous avez pu implémenter l'authentification d'utilisateur pour le client et le serveur. Angular utilise TypeScript, un sur-ensemble du langage JavaScript, qui ajoute des informations de type. TypeScript rend le code plus stable et c'est pourquoi j'ai décidé d'implémenter également le serveur Node / Express en utilisant ce langage. Si vous n'êtes pas encore familiarisé avec TypeScript, consultez cette excellente introduction de Todd Motto . Il a également de bons articles sur Angular.

Le code complet de ce tutoriel est disponible sur [GitHub .

Si vous êtes prêt à en savoir plus sur Angular, ou Node / Express, nous Ayez d’autres ressources à consulter:

Et comme toujours, nous aimerions que vous nous suiviez pour obtenir du contenu plus cool et des mises à jour de notre équipe. Vous pouvez nous trouver sur Twitter @oktadev sur Facebook et LinkedIn .






Source link