#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()
или аналогично setupcourse
в качестве горячей наблюдаемой.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>