{ "id": "start/start-data", "title": "Managing data", "contents": "\n\n\n
\n mode_edit\n
\n\n\n
\n

Managing datalink

\n

This guide builds on the second step of the Getting started with a basic Angular application tutorial, Adding navigation.\nAt this stage of development, the store application has a product catalog with two views: a product list and product details.\nUsers can click on a product name from the list to see details in a new view, with a distinct URL, or route.

\n

This step of the tutorial guides you through creating a shopping cart in the following phases:

\n\n\n

Create the shopping cart servicelink

\n

In Angular, a service is an instance of a class that you can make available to any part of your application using Angular's dependency injection system.

\n

Currently, users can view product information, and the application can simulate sharing and notifications about product changes.

\n

The next step is to build a way for users to add products to a cart.\nThis section walks you through adding a Buy button and setting up a cart service to store information about products in the cart.

\n\n

Define a cart servicelink

\n
    \n
  1. \n

    To generate a cart service, right click on the app folder, choose Angular Generator, and choose Service.\nName the new service cart.

    \n\nimport { Injectable } from '@angular/core';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class CartService {\n\n constructor() {}\n\n}\n\n\n\n
  2. \n
  3. \n

    In the CartService class, define an items property to store the array of the current products in the cart.

    \n\nexport class CartService {\n items = [];\n}\n\n\n
  4. \n
  5. \n

    Define methods to add items to the cart, return cart items, and clear the cart items.

    \n\nexport class CartService {\n items = [];\n\n addToCart(product) {\n this.items.push(product);\n }\n\n getItems() {\n return this.items;\n }\n\n clearCart() {\n this.items = [];\n return this.items;\n }\n}\n\n\n
      \n
    • \n

      The addToCart() method appends a product to an array of items.

      \n
    • \n
    • \n

      The getItems() method collects the items users add to the cart and returns each item with its associated quantity.

      \n
    • \n
    • \n

      The clearCart() method returns an empty array of items, which empties the cart.

      \n
    • \n
    \n
  6. \n
\n\n

Use the cart servicelink

\n

This section walks you through using the CartService to add a product to the cart.

\n
    \n
  1. \n

    In product-details.component.ts, import the cart service.

    \n\nimport { Component, OnInit } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\n\nimport { products } from '../products';\nimport { CartService } from '../cart.service';\n\n\n
  2. \n
  3. \n

    Inject the cart service by adding it to the constructor().

    \n\nexport class ProductDetailsComponent implements OnInit {\n constructor(\n private route: ActivatedRoute,\n private cartService: CartService\n ) { }\n}\n\n\n\n
  4. \n
  5. \n

    Define the addToCart() method, which adds the current product to the cart.

    \n\nexport class ProductDetailsComponent implements OnInit {\n addToCart(product) {\n this.cartService.addToCart(product);\n window.alert('Your product has been added to the cart!');\n }\n}\n\n\n\n

    The addToCart() method does the following:

    \n
      \n
    • Takes the current product as an argument.
    • \n
    • Uses the CartService addToCart() method to add the product to the cart.
    • \n
    • Displays a message that you've added a product to the cart.
    • \n
    \n
  6. \n
  7. \n

    In product-details.component.html, add a button with the label Buy, and bind the click() event to the addToCart() method.\nThis code updates the product details template with a Buy button that adds the current product to the cart.

    \n\n<h2>Product Details</h2>\n\n<div *ngIf=\"product\">\n <h3>{{ product.name }}</h3>\n <h4>{{ product.price | currency }}</h4>\n <p>{{ product.description }}</p>\n\n <button (click)=\"addToCart(product)\">Buy</button>\n</div>\n\n\n\n
  8. \n
  9. \n

    Verify that the new Buy button appears as expected by refreshing the application and clicking on a product's name to display its details.

    \n
    \n \"Display\n
    \n
  10. \n
  11. \n

    Click the Buy button to add the product to the stored list of items in the cart and display a confirmation message.

    \n
    \n \"Display\n
    \n
  12. \n
\n

Create the cart viewlink

\n

For customers to see their cart, you can create the cart view in two steps:

\n
    \n
  1. Create a cart component and configure routing to the new component.
  2. \n
  3. Display the cart items.
  4. \n
\n

Set up the cart componentlink

\n

To create the cart view, follow the same steps you did to create the ProductDetailsComponent and configure routing for the new component.

\n
    \n
  1. \n

    Generate a cart component named cart by right-clicking the app folder, choosing Angular Generator, and Component.

    \n\nimport { Component } from '@angular/core';\n\n@Component({\n selector: 'app-cart',\n templateUrl: './cart.component.html',\n styleUrls: ['./cart.component.css']\n})\nexport class CartComponent {\n\n constructor() { }\n\n}\n\n\n\n

    StackBlitz also generates an ngOnInit() by default in components. You can ignore the CartComponent ngOnInit() for this tutorial.

    \n
  2. \n
  3. \n

    Open app.module.ts and add a route for the component CartComponent, with a path of cart.

    \n\n\n@NgModule({\n imports: [\n BrowserModule,\n ReactiveFormsModule,\n RouterModule.forRoot([\n { path: '', component: ProductListComponent },\n { path: 'products/:productId', component: ProductDetailsComponent },\n { path: 'cart', component: CartComponent },\n ])\n ],\n\n\n
  4. \n
  5. \n

    Update the Checkout button so that it routes to the /cart URL.\nIn top-bar.component.html, add a routerLink directive pointing to /cart.

    \n\n<a routerLink=\"/cart\" class=\"button fancy-button\">\n <i class=\"material-icons\">shopping_cart</i>Checkout\n</a>\n\n\n
  6. \n
  7. \n

    Verify the new CartComponent works as expected by clicking the Checkout button.\nYou can see the \"cart works!\" default text, and the URL has the pattern https://getting-started.stackblitz.io/cart, where getting-started.stackblitz.io may be different for your StackBlitz project.

    \n
    \n \"Display\n
    \n
  8. \n
\n

Display the cart itemslink

\n

This section shows you how to use the cart service to display the products in the cart.

\n
    \n
  1. \n

    In cart.component.ts, import the CartService from the cart.service.ts file.

    \n\nimport { Component } from '@angular/core';\nimport { CartService } from '../cart.service';\n\n\n
  2. \n
  3. \n

    Inject the CartService so that the CartComponent can use it by adding it to the constructor().

    \n\nexport class CartComponent {\n\n constructor(\n private cartService: CartService\n ) { }\n}\n\n\n\n
  4. \n
  5. \n

    Define the items property to store the products in the cart.

    \n\nexport class CartComponent {\n items = this.cartService.getItems();\n\n constructor(\n private cartService: CartService\n ) { }\n}\n\n\n\n

    This code sets the items using the CartService getItems() method.\nYou defined this method when you created cart.service.ts.

    \n
  6. \n
  7. \n

    Update the cart template with a header, and use a <div> with an *ngFor to display each of the cart items with its name and price.\nThe resulting CartComponent template is as follows.

    \n\n<h3>Cart</h3>\n\n<div class=\"cart-item\" *ngFor=\"let item of items\">\n <span>{{ item.name }}</span>\n <span>{{ item.price | currency }}</span>\n</div>\n\n\n
  8. \n
  9. \n

    Verify that your cart works as expected:

    \n
      \n
    • Click My Store
    • \n
    • Click on a product name to display its details.
    • \n
    • Click Buy to add the product to the cart.
    • \n
    • Click Checkout to see the cart.
    • \n
    \n
    \n \"Cart\n
    \n
  10. \n
\n

For more information about services, see Intro to Services and DI\">Introduction to Services and Dependency Injection.

\n

Retrieve shipping priceslink

\n

Servers often return data in the form of a stream.\nStreams are useful because they make it easy to transform the returned data and make modifications to the way you request that data.\nAngular HttpClient is a built-in way to fetch data from external APIs and provide them to your application as a stream.

\n

This section shows you how to use HttpClient to retrieve shipping prices from an external file.

\n

The application that StackBlitz generates for this guide comes with predefined shipping data in assets/shipping.json.\nUse this data to add shipping prices for items in the cart.

\n\n[\n {\n \"type\": \"Overnight\",\n \"price\": 25.99\n },\n {\n \"type\": \"2-Day\",\n \"price\": 9.99\n },\n {\n \"type\": \"Postal\",\n \"price\": 2.99\n }\n]\n\n\n

Configure AppModule to use HttpClientlink

\n

To use Angular's HttpClient, you must configure your application to use HttpClientModule.

\n

Angular's HttpClientModule registers the providers your application needs to use the HttpClient service throughout your application.

\n
    \n
  1. \n

    In app.module.ts, import HttpClientModule from the @angular/common/http package at the top of the file with the other imports.\nAs there are a number of other imports, this code snippet omits them for brevity.\nBe sure to leave the existing imports in place.

    \n\nimport { HttpClientModule } from '@angular/common/http';\n\n\n
  2. \n
  3. \n

    To register Angular's HttpClient providers globally, add HttpClientModule to the AppModule @NgModule() imports array.

    \n\n\n@NgModule({\n imports: [\n BrowserModule,\n HttpClientModule,\n ReactiveFormsModule,\n RouterModule.forRoot([\n { path: '', component: ProductListComponent },\n { path: 'products/:productId', component: ProductDetailsComponent },\n { path: 'cart', component: CartComponent },\n ])\n ],\n declarations: [\n AppComponent,\n TopBarComponent,\n ProductListComponent,\n ProductAlertsComponent,\n ProductDetailsComponent,\n CartComponent,\n ],\n bootstrap: [\n AppComponent\n ]\n})\nexport class AppModule { }\n\n\n\n
  4. \n
\n

Configure CartService to use HttpClientlink

\n

The next step is to inject the HttpClient service into your service so your application can fetch data and interact with external APIs and resources.

\n
    \n
  1. \n

    In cart.service.ts, import HttpClient from the @angular/common/http package.

    \n\nimport { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\n\n
  2. \n
  3. \n

    Inject HttpClient into the CartService constructor().

    \n\nexport class CartService {\n items = [];\n\n constructor(\n private http: HttpClient\n ) {}\n}\n\n\n
  4. \n
\n

Configure CartService to get shipping priceslink

\n

To get shipping data, from shipping.json, You can use the HttpClient get() method.

\n
    \n
  1. \n

    In cart.service.ts, below the clearCart() method, define a new getShippingPrices() method that uses the HttpClient get() method.

    \n\nexport class CartService {\n getShippingPrices() {\n return this.http.get<{type: string, price: number}[]>('/assets/shipping.json');\n }\n}\n\n\n\n
  2. \n
\n

For more information about Angular's HttpClient, see the Client-Server Interaction guide.

\n

Create a shipping componentlink

\n

Now that you've configured your application to retrieve shipping data, you can create a place to render that data.

\n
    \n
  1. \n

    Generate a new component named shipping by right-clicking the app folder, choosing Angular Generator, and selecting Component.

    \n\nimport { Component } from '@angular/core';\n\n@Component({\n selector: 'app-shipping',\n templateUrl: './shipping.component.html',\n styleUrls: ['./shipping.component.css']\n})\nexport class ShippingComponent {\n\n constructor() { }\n\n}\n\n\n\n
  2. \n
  3. \n

    In app.module.ts, add a route for shipping.\nSpecify a path of shipping and a component of ShippingComponent.

    \n\n\n@NgModule({\n imports: [\n BrowserModule,\n HttpClientModule,\n ReactiveFormsModule,\n RouterModule.forRoot([\n { path: '', component: ProductListComponent },\n { path: 'products/:productId', component: ProductDetailsComponent },\n { path: 'cart', component: CartComponent },\n { path: 'shipping', component: ShippingComponent },\n ])\n ],\n declarations: [\n AppComponent,\n TopBarComponent,\n ProductListComponent,\n ProductAlertsComponent,\n ProductDetailsComponent,\n CartComponent,\n ShippingComponent\n ],\n bootstrap: [\n AppComponent\n ]\n})\nexport class AppModule { }\n\n\n\n

    There's no link to the new shipping component yet, but you can see its template in the preview pane by entering the URL its route specifies.\nThe URL has the pattern: https://getting-started.stackblitz.io/shipping where the getting-started.stackblitz.io part may be different for your StackBlitz project.

    \n
  4. \n
\n

Configuring the ShippingComponent to use CartServicelink

\n

This section guides you through modifying the ShippingComponent to retrieve shipping data via HTTP from the shipping.json file.

\n
    \n
  1. \n

    In shipping.component.ts, import CartService.

    \n\nimport { Component } from '@angular/core';\n\nimport { CartService } from '../cart.service';\n\n\n
  2. \n
  3. \n

    Inject the cart service in the ShippingComponent constructor().

    \n\nconstructor(private cartService: CartService) {\n}\n\n\n
  4. \n
  5. \n

    Define a shippingCosts property that sets the shippingCosts property using the getShippingPrices() method from the CartService.

    \n\nexport class ShippingComponent {\n shippingCosts = this.cartService.getShippingPrices();\n}\n\n\n\n
  6. \n
  7. \n

    Update the ShippingComponent template to display the shipping types and prices using the async pipe.

    \n\n<h3>Shipping Prices</h3>\n\n<div class=\"shipping-item\" *ngFor=\"let shipping of shippingCosts | async\">\n <span>{{ shipping.type }}</span>\n <span>{{ shipping.price | currency }}</span>\n</div>\n\n\n\n

    The async pipe returns the latest value from a stream of data and continues to do so for the life of a given component.\nWhen Angular destroys that component, the async pipe automatically stops.\nFor detailed information about the async pipe, see the AsyncPipe API documentation.

    \n
  8. \n
  9. \n

    Add a link from the CartComponent view to the ShippingComponent view.

    \n\n<h3>Cart</h3>\n\n<p>\n <a routerLink=\"/shipping\">Shipping Prices</a>\n</p>\n\n<div class=\"cart-item\" *ngFor=\"let item of items\">\n <span>{{ item.name }}</span>\n <span>{{ item.price | currency }}</span>\n</div>\n\n\n\n
  10. \n
  11. \n

    Click the Checkout button to see the updated cart.\nRemember that changing the application causes the preview to refresh, which empties the cart.

    \n
    \n \"Cart\n
    \n

    Click on the link to navigate to the shipping prices.

    \n
    \n \"Display\n
    \n
  12. \n
\n

What's nextlink

\n

You now have a store application with a product catalog, a shopping cart, and you can look up shipping prices.

\n

To continue exploring Angular:

\n\n\n \n
\n\n\n" }