JorisSchelfaut / angular-dev-tutorial-first-app

Project following the Angular tutorial on angular.io
MIT License
0 stars 0 forks source link

Add HTTP communication #14

Closed JorisSchelfaut closed 3 months ago

JorisSchelfaut commented 4 months ago

1. Configure the JSON server

JSON Server is an open source tool used to create mock REST APIs. You'll use it to serve the housing location data that is currently stored in the housing service.

  1. Install json-server from npm by using the following command.

    npm install -g json-server
  2. In the root directory of your project, create a file called db.json. This is where you will store the data for the json-server.

  3. Open db.json and copy the following code into the file

    {
         "locations": [
             {
                 "id": 0,
                 "name": "Acme Fresh Start Housing",
                 "city": "Chicago",
                 "state": "IL",
                 "photo": "${this.baseUrl}/bernard-hermant-CLKGGwIBTaY-unsplash.jpg",
                 "availableUnits": 4,
                 "wifi": true,
                 "laundry": true
             },
             {
                 "id": 1,
                 "name": "A113 Transitional Housing",
                 "city": "Santa Monica",
                 "state": "CA",
                 "photo": "${this.baseUrl}/brandon-griggs-wR11KBaB86U-unsplash.jpg",
                 "availableUnits": 0,
                 "wifi": false,
                 "laundry": true
             },
             {
                 "id": 2,
                 "name": "Warm Beds Housing Support",
                 "city": "Juneau",
                 "state": "AK",
                 "photo": "${this.baseUrl}/i-do-nothing-but-love-lAyXdl1-Wmc-unsplash.jpg",
                 "availableUnits": 1,
                 "wifi": false,
                 "laundry": false
             },
             {
                 "id": 3,
                 "name": "Homesteady Housing",
                 "city": "Chicago",
                 "state": "IL",
                 "photo": "${this.baseUrl}/ian-macdonald-W8z6aiwfi1E-unsplash.jpg",
                 "availableUnits": 1,
                 "wifi": true,
                 "laundry": false
             },
             {
                 "id": 4,
                 "name": "Happy Homes Group",
                 "city": "Gary",
                 "state": "IN",
                 "photo": "${this.baseUrl}/krzysztof-hepner-978RAXoXnH4-unsplash.jpg",
                 "availableUnits": 1,
                 "wifi": true,
                 "laundry": false
             },
             {
                 "id": 5,
                 "name": "Hopeful Apartment Group",
                 "city": "Oakland",
                 "state": "CA",
                 "photo": "${this.baseUrl}/r-architecture-JvQ0Q5IkeMM-unsplash.jpg",
                 "availableUnits": 2,
                 "wifi": true,
                 "laundry": true
             },
             {
                 "id": 6,
                 "name": "Seriously Safe Towns",
                 "city": "Oakland",
                 "state": "CA",
                 "photo": "${this.baseUrl}/phil-hearing-IYfp2Ixe9nM-unsplash.jpg",
                 "availableUnits": 5,
                 "wifi": true,
                 "laundry": true
             },
             {
                 "id": 7,
                 "name": "Hopeful Housing Solutions",
                 "city": "Oakland",
                 "state": "CA",
                 "photo": "${this.baseUrl}/r-architecture-GGupkreKwxA-unsplash.jpg",
                 "availableUnits": 2,
                 "wifi": true,
                 "laundry": true
             },
             {
                 "id": 8,
                 "name": "Seriously Safe Towns",
                 "city": "Oakland",
                 "state": "CA",
                 "photo": "${this.baseUrl}/saru-robert-9rP3mxf8qWI-unsplash.jpg",
                 "availableUnits": 10,
                 "wifi": false,
                 "laundry": false
             },
             {
                 "id": 9,
                 "name": "Capital Safe Towns",
                 "city": "Portland",
                 "state": "OR",
                 "photo": "${this.baseUrl}/webaliser-_TPTXZd9mOo-unsplash.jpg",
                 "availableUnits": 6,
                 "wifi": true,
                 "laundry": true
             }
         ]
     }
  4. Save this file.

  5. Time to test your configuration. From the command line, at the root of your project run the following commands.

    json-server --watch db.json
  6. In your web browser, navigate to the http://localhost:3000/locations and confirm that the response includes the data stored in db.json.

If you have any trouble with your configuration, you can find more details in the official documentation.

2. Update service to use web server instead of local array

The data source has been configured, the next step is to update your web app to connect to it use the data.

  1. In src/app/housing.service.ts, make the following changes:

    1. Update the code to remove housingLocationList property and the array containing the data.

    2. Add a string property called url and set its value to 'http://localhost:3000/locations'

      url = 'http://localhost:3000/locations';

      This code will result in errors in the rest of the file because it depends on the housingLocationList property. We're going to update the service methods next.

    3. Update the getAllHousingLocations function to make a call to the web server you configured. adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts

        async getAllHousingLocations(): Promise<HousingLocation[]> {
          const data = await fetch(this.url);
          return (await data.json()) ?? [];
        }

      The code now uses asynchronous code to make a GET request over HTTP.

      HELPFUL: For this example, the code uses fetch. For more advanced use cases consider using HttpClient provided by Angular.

    4. Update the getHousingLocationsById function to make a call to the web server you configured. adev/src/content/tutorials/first-app/steps/14-http/src-final/app/housing.service.ts

        async getHousingLocationById(id: number): Promise<HousingLocation | undefined> {
          const data = await fetch(`${this.url}/${id}`);
          return (await data.json()) ?? {};
        }
    5. Once all the updates are complete, your updated service should match the following code. Final version of housing.service.ts

      import {Injectable} from '@angular/core';
      import {HousingLocation} from './housinglocation';
      @Injectable({
        providedIn: 'root',
      })
      export class HousingService {
        url = 'http://localhost:3000/locations';
        async getAllHousingLocations(): Promise<HousingLocation[]> {
          const data = await fetch(this.url);
          return (await data.json()) ?? [];
        }
        async getHousingLocationById(id: number): Promise<HousingLocation | undefined> {
          const data = await fetch(`${this.url}/${id}`);
          return (await data.json()) ?? {};
        }
        submitApplication(firstName: string, lastName: string, email: string) {
          // tslint:disable-next-line
          console.log(firstName, lastName, email);
        }
      }

3. Update the components to use asynchronous calls to the housing service

The server is now reading data from the HTTP request but the components that rely on the service now have errors because they were programmed to use the synchronous version of the service.

  1. In src/app/home/home.component.ts, update the constructor to use the new asynchronous version of the getAllHousingLocations method. adev/src/content/tutorials/first-app/steps/14-http/src-final/app/home/home.component.ts

      constructor() {
        this.housingService.getAllHousingLocations().then((housingLocationList: HousingLocation[]) => {
          this.housingLocationList = housingLocationList;
          this.filteredLocationList = housingLocationList;
        });
      }
  2. In src/app/details/details.component.ts, update the constructor to use the new asynchronous version of the getHousingLocationById method. adev/src/content/tutorials/first-app/steps/14-http/src-final/app/details/details.component.ts

      constructor() {
        const housingLocationId = parseInt(this.route.snapshot.params['id'], 10);
        this.housingService.getHousingLocationById(housingLocationId).then((housingLocation) => {
          this.housingLocation = housingLocation;
        });
      }
  3. Save your code.

  4. Open the application in the browser and confirm that it runs without any errors.