проблема рефакторинга к реактивному программированию в angular - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь рефакторинг в реактивном программировании, но я столкнулся с препятствием. Ниже я опубликую исходный код и модифицированный для рефакторинга. Проблема в том, что имя пользователя не отображается на веб-странице. Когда страница загружается, она отображает «Загрузка ...» через несколько секунд, она исчезает, но не заменяется ником, что следует делать в соответствии с кодом шаблона. Что случилось?

ОРИГИНАЛЬНЫЙ КОД user.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders , HttpParams } from '@angular/common/http';

import { User } from '../models/user';
import { tap, map } from 'rxjs/operators';
import { Car } from '../models/car';

@Injectable({ providedIn: 'root' })
export class UserService {

    headers = new HttpHeaders({
        'Content-Type':  'application/json',
        'Authorization': 'application/json'
    });

    host = 'http://localhost:8080/';

    constructor(private http: HttpClient) { }

    register(user: User) {

        let params = new HttpParams()
            .set('username', user.username)
            .set('firstname', user.firstName)
            .set('lastname', user.lastName)
            .set('password', user.password)
            .set('email', user.email)

        let options = {headers:this.headers, params:params}    
        return this.http.post(this.host + 'register', options );
    }

    getUser(userId:number){
        let params = new HttpParams().set('userId', String(userId));
        let options = { headers: this.headers, params: params };

        return this.http.get(this.host + 'getUserById', options);
    }

}

user-page.component.ts

import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
import { User } from '../models/user';
import { ActivatedRoute, ParamMap } from '@angular/router';

@Component({
  selector: 'app-user-page',
  templateUrl: './user-page.component.html',
  styleUrls: ['./user-page.component.css']
})
export class UserPageComponent implements OnInit {

  user = new User;
  userId:number = null;
  subscriptionUserId;
  subscriptionUser;

  constructor(private userService:UserService, private route: ActivatedRoute) { 
    this.subscriptionUserId = this.route.paramMap.subscribe((params : ParamMap)=> {  
      this.userId = parseInt(params.get('userId'));
    });
  }

  ngOnInit() {

    this.subscriptionUser = this.userService.getUser(this.userId).subscribe( data => {

      this.user.firstName = data[0].firstname;
      this.user.lastName = data[0].lastname;
      this.user.username = data[0].username;

    }, error => {
      console.error(error);
    })
  }

  ngOnDestroy(){
    this.subscriptionUserId.unsubscribe();
    this.subscriptionUser.unsubscribe();
  }
}

user-page.component. html

<body>
    <h2>Welcome to User Page</h2>
    <div class="containerUser">
        <div class="items"><h2 class="sellerUsername"><b>{{user?.username}}</b></h2></div>
        <div class="items"><app-star-rating userId="{{userId}}"></app-star-rating></div>
    </div>
    <app-user-gallery [userId]="userId"></app-user-gallery>
</body>

РЕФАКТОРНЫЙ КОД user.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders , HttpParams } from '@angular/common/http';

import { User } from '../models/user';
import { tap, map, shareReplay } from 'rxjs/operators';
import { Car } from '../models/car';
import { Observable } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class UserService {

    headers = new HttpHeaders({
        'Content-Type':  'application/json',
        'Authorization': 'application/json'
    });

    host = 'http://localhost:8080/';

    user:Observable<User>;

    constructor(private http: HttpClient) { }

    register(user: User) {

        let params = new HttpParams()
            .set('username', user.username)
            .set('firstname', user.firstName)
            .set('lastname', user.lastName)
            .set('password', user.password)
            .set('email', user.email)

        let options = {headers:this.headers, params:params}    
        return this.http.post(this.host + 'register', options );
    }

    getUserById(userId:number){
        let params = new HttpParams().set('userId', String(userId));
        let options = { headers: this.headers, params: params };

        this.user = this.http.get(this.host + 'getUserById', options)
            .pipe(
                map( response => response as User ),
                tap( user => console.log(user) )
            );
    }

}

user-page.component. html

<body>
    <h2>Welcome to User Page</h2>
    <div class="containerUser">
        <div class="items" *ngIf="userService.user | async as user$; else loading">
            <h2 class="sellerUsername"><b>{{user$.username}}</b></h2>
        </div>
        <ng-template #loading>Loading...</ng-template>
        <div class="items"><app-star-rating userId="{{userId}}"></app-star-rating></div>
    </div>
    <app-user-gallery [userId]="userId"></app-user-gallery>
</body>

1 Ответ

1 голос
/ 04 марта 2020

Следующее должно заставить ваш реорганизованный шаблон работать с синтаксисом *ngIf и else, который вы используете в шаблоне.

Проверьте этот Stackblitz, основанный на вашем коде, который выделит шаблон, который вы здесь: https://stackblitz.com/edit/angular-nowbcs?file=src%2Fapp%2Fapp.component.ts

Ваш сервис должен иметь метод с именем getUser(), который возвращает Observable<User>.

getUser(userId): Observable<User> {
    let params = new HttpParams().set('userId', String(userId));
    let options = { headers: this.headers, params: params };
    return this.http.get(this.host + 'getUserById', options)
        .pipe(
            map((userResponse: User[]) => { // you only need to use map if you need to modify the structure of the response
                 return users[0]; // returns only the first user in the array that you get from the API
            })
        )
}

Ваш компонент ngOnInit() метод должен:

    user$: Observable<User>; // define this property on your component

    ngOnInit(): void {
        this.user$ = this.userService.getUser();
        // if you need a userId for the `getUser()` then make sure
        // the userId is inside your `.subscribe()` to the route params
    }

Ваш шаблон должен выглядеть аналогично вашему рефакторинному коду:

<body>
    <h2>Welcome to User Page</h2>
    <div class="containerUser">
        <div class="items" *ngIf="(user$ | async) as user; else loading">
            <h2 class="sellerUsername"><b>{{user.username}}</b></h2>
            <app-user-gallery [userId]="user.userId"></app-user-gallery>
            <div class="items">
                <app-star-rating [userId]="user.userId"></app-star-rating></div>
            </div>
        </div>  
        <ng-template #loading>Loading...</ng-template>
    </div>
</body>
...