Отображение загрузки при использовании Observable с асинхронным каналом в шаблоне

#angular #ionic2 #observable #angularfire2

#angular #ionic2 #наблюдаемый #angularfire2

Вопрос:

Ситуация: я использую FirebaseObjectObservable для заполнения моего шаблона Ionic 2 (rc0). Код шаблона:

 <ion-card-content>
  <p>{{(course | async)?.description}}</p>
  <br>
  <h2>Learning Objectives</h2>
  <ul>
    <li *ngFor = "let objective of (course | async)?.objectives">{{objective.text}}</li>
  </ul>
  <h2>Takeaway</h2>
  <ul>
    <li *ngFor = "let takeaway of (course | async)?.takeaways">{{takeaway.text}}</li>
  </ul>
</ion-card-content>
  

TS-код:

 this.course = this.af.database.object('/bbwLocations/courses/'   courseId); 
  

this.course является объектом Firebase Observable. Все работает! Но всякий раз, когда я захожу в шаблон, появляется вспышка пустых данных. Затем все данные выскакивают! Очень не дружественный к UX. Итак, я хочу использовать какую-то стратегию предварительной загрузки. Но поскольку здесь нет логики TS. Все контролируется на уровне шаблона с помощью асинхронного канала. Как бы мне добавить загрузку в этой ситуации?

Комментарии:

1. Распознаватель маршрутов — это удобный способ обработки предварительных условий просмотра.

2. Что вы имеете в виду Router resolver? Я нахожусь в Ionic 2 RC0. Я считаю, что маршрутизатора нет.

3. Я не использую Ionic, но, по крайней мере, это достижимо с маршрутизатором A2 angular.io/docs/ts/latest/guide/router.html #!#resolve-guard Я не знаю, насколько хорошо I2 работает с маршрутизатором A2. В любом случае, лучший способ справиться с этим — разрешить зависимость перед инициализацией компонента (например, перед nav.push вызовом, если вы используете его для навигации).

Ответ №1:

Может быть, немного поздно, но на случай, если кому-то еще интересно, как с этим справиться… Как насчет использования шаблона?

вы могли бы, например, использовать что-то вроде:

 <ion-card-content *ngIf='(course$ | async) as course; else loading'>
  <p>{{course.description}}</p>
  <br>
  <h2>Learning Objectives</h2>
  <ul>
     <li *ngFor = "let objective of course.objectives"> 
         {{objective.text}}</li>
  </ul>
  <h2>Takeaway</h2>
  <ul>
     <li *ngFor = "let takeaway of course.takeaways"> 
         {{takeaway.text}}</li>
  </ul>
</ion-card-content>

<ng-template #loading>
  Loading stuff...
</ng-template>
  

таким образом, ваш ion-card-content будет скрыт, показывая #template, пока не будет загружен асинхронный канал.

Ответ №2:

Вы могли бы сделать что-то вроде этого:

 <style>
  pre {
   color: orange;
   // or whatever you want
  }
</style>
<ion-card-content>
  <p>{{(course | async)?.description}}</p>
  <br>
  <h2>Learning Objectives</h2>
  <pre *ngIf="!(course | async)">loading objectives...</pre>
  <ul>
    <li *ngFor = "let objective of (course | async)?.objectives">{{objective.text}}</li>
  </ul>
  <h2>Takeaway</h2>
  <pre *ngIf="!(course | async)">loading takeaways...</pre>
  <ul>
    <li *ngFor = "let takeaway of (course | async)?.takeaways">{{takeaway.text}}</li>
  </ul>
</ion-card-content>
  

Комментарии:

1. Это работает. Но если я хочу анимацию выхода, например, отключить загрузчик, когда ngIf станет ложным. Я не смогу этого сделать. Кроме того, возможно ли подключиться к observable и использовать для этого компонент Ionic Loader?

2. Если вы хотите использовать ngIf , я считаю Animations , что это правильный путь. Вы могли бы использовать ngClass вместо ngIf и выполнять анимацию / переходы с помощью CSS. transition: 1s opacity 0.5s linear , и тому подобное…

3. Не могли бы вы обновить свое решение и привести пример, как легко использовать анимацию для затухания элемента pre? Спасибо!

4. Но это делает много ненужных запросов … 🙁

5. Если он дублирует ваш запрос: вы предоставляете наблюдателям доступ к холодному наблюдаемому. Вы должны использовать share() или аналогично setup course в качестве горячей наблюдаемой. this.course = this.httpClient.get('whatever').pipe(shareReplay(1)) . это сохранит самый последний результат, так что, если у вас несколько подписчиков: они могут наблюдать за воспроизведением результата вместо инициирования нового HTTP-запроса.

Ответ №3:

Допустим, у нас есть наблюдаемое питание $. Нам нужно показать загрузчик, когда observable будет разрешен (т.е. выборка данных). Ниже приведено решение.

 <div *ngIf="meal$ | async as meal; else loading;" >
   //use the meal variable to show some data
</div>
<ng-template #loading>
   //Show your loader here
</ng-template>