Angular 8 использует ngIf с асинхронным каналом, чтобы показать и скрыть элемент HTML - PullRequest
0 голосов
/ 08 октября 2019

Я пытаюсь показать и скрыть элементы HTML в соответствии с результатом службы. Я использую *ngIf="messageService.getData() | async", но он не работает, чтобы показать или скрыть элемент. Я использую асинхронный режим, в противном случае на короткое время отображается сообщение об ошибке, а затем отображается сообщение об успешном сообщении.

У меня есть 2 таких тега:

<div *ngIf="messageService.getData() | async">Successful Message</div>
<div *ngIf="!messageService.getData() | async">Failure Message</div>

В службеУ меня есть такой код:

export class MessageService {
  constructor(private http: HttpClient) { }

  public getData() {
    return this.http.get("https://jsonplaceholder.typicode.com/todos/1")
    .pipe(
      map((response) => {
        console.log("success");
      }),
      catchError(this.handleError)
    )
  }

  private handleError(error: Response) {
    console.log("handleError")
    let errMsg: string;
    errMsg = "error"
    return Observable.throw(errMsg);
  }
}

Вот исходный код: https://stackblitz.com/edit/angular-iqr6az

Ответы [ 5 ]

4 голосов
/ 08 октября 2019

в вашем сервисе:

public getData() {
    return this.http.get("https://jsonplaceholder.typicode.com/todos/1")
    .pipe(
      map((response) => {
        return response; // return res
      }),
      catchError(this.handleError)
    )
  }

в вашем компоненте:

export class MessageComponent implements OnInit {
  isServiceAPIWorking: boolean;
  todos;
  loadingError$ = new Subject<boolean>();
  constructor(private messageService: MessageService) { }

  ngOnInit() {
    this.todos = this.messageService.getData().pipe(
      catchError((error) => {
        // it's important that we log an error here.
        // Otherwise you won't see an error in the console.
        console.error('error loading the list of users', error);
        this.loadingError$.next(true);
        return of();
      })
    );
  }
}

в вашем html:

<div>Show Message:</div>
<div *ngIf="todos | async">Successfull Message</div>
<div *ngIf="loadingError$ | async">Failure Message</div>

DEMO ?? .

1 голос
/ 08 октября 2019

Это неправильное использование async канала не в синтаксическом, а в семантическом смысле. Каждый раз, когда обнаруживается изменение, вы делаете HTTP-запрос.

Вместо проверки с помощью async pipe вы можете хранить два флага (логические переменные) или одну логическую переменную для HTTP-запроса и одну переменную для ответа. .

Ниже приведен пример использования двух флагов.

export class MessageService {

  isLoaded = false;
  hasError  = false;

  constructor(private http: HttpClient) { }

  public getData() {
    this.isLoaded = false;
    this.http.get("https://jsonplaceholder.typicode.com/todos/1")
    .subscribe(
       (response) => {
           this.hasError = false;
           this.isLoaded = true;
       },
       (error) => {  
           this.hasError = true;
           this.isLoaded = true;
       },
    )
  }
}

И в шаблоне:

<ng-container *ngIf="isLoaded">
    <div *ngIf="!hasError">Successfull Message</div>
    <div *ngIf="hasError">Failure Message</div>
</ng-container>
1 голос
/ 08 октября 2019

Зачем беспокоиться об асинхронных каналах, когда вы можете просто назначить данные в вашем компоненте?

// message.component.ts

class MessageComponent implements OnInit {
  isServiceAPIWorking: boolean;
  data: any;
  constructor(private messageService: MessageService) { }

  ngOnInit() {
    this.messageService.getData()
      .subscribe(response => {
        this.isServiceAPIWorking = true;
        // Assign the data
        this.data = response;
      },
        error => {
          this.isServiceAPIWorking = false;
        })
  }
}
// message.component.html

<div>Show Message:</div>
<div *ngIf="data">Successfull Message</div>
<div *ngIf="!data">Failure Message</div>

И в вашем сервисе есть ошибка. Если вы используете map, ничего не возвращая, вы не получите никаких данных. Используйте tap, если вы хотите сделать запись:

// message.service.ts

public getData() {
  return this.http.get("https://jsonplaceholder.typicode.com/todos/1")
  .pipe(
    tap((response) => {
      console.log("success");
    }),
    catchError(this.handleError)
  )
}

Обновлен Stackblitz

0 голосов
/ 08 октября 2019

Объявите переменную Observable в вашем компоненте. Давайте назовем это response: Observable<any>.

MessageComponent.ts

export class MessageComponent implements OnInit {
  response: Observable<any>;
  constructor(private messageService: MessageService) { }

  ngOnInit() {
    this.response = this.messageService.getData();
  }
}

MessageComponent.html

<div>Show Message:</div>
<div *ngIf="response | async">Successful Message</div>
<div *ngIf="!response | async">Failure Message</div>

MessageService.ts

public getData() {
  return this.http.get("https://jsonplaceholder.typicode.com/todos/1");
}

Канал async подписывается на response, наблюдаемый сейчас.

0 голосов
/ 08 октября 2019

Нет необходимости иметь два *ngIf:

<div *ngIf="messageService.getData() | async; else noContent">Successfull Message</div>

<ng-template #noContent>
    <span>No Content </span>
</ng-template>
...