Ждать угловая 2 для загрузки/решения модели до визуализации вид/шаблон


В Угловой 1.x, UI-маршрутизатор был моим основным инструментом для этого. Возвращая обещание для значений "resolve", маршрутизатор будет просто ждать завершения обещания перед выполнением директив рендеринга.

поочередно, в угловой 1.x, нулевой объект не приведет к сбою шаблона - поэтому, если я не возражаю против временно неполного рендеринга, я могу просто использовать $digest для рендеринга после promise.then() заполняет изначально пустой объект модели.

из двух подходов, если это возможно, я бы предпочел чтобы дождаться загрузки представления и отменить навигацию по маршруту, если ресурс не может быть загружен. Это избавляет меня от работы "без навигации". EDIT: обратите внимание, что это конкретно означает, что этот вопрос запрашивает метод Angular 2 futures-compatible или best-practice для этого и просит избегать "оператора Элвиса", если это возможно! Таким образом, я не выбрал этот ответ.

однако ни один из этих двух методов не работает в Angular 2.0. Конечно, есть стандартное решение, запланированное или доступное для этот. Кто-нибудь знает, что это такое?

@Component() {
    template: '{{cats.captchans.funniest}}'
}
export class CatsComponent {

    public cats: CatsModel;

    ngOnInit () {
        this._http.get('/api/v1/cats').subscribe(response => cats = response.json());
    }
}

следующий вопрос может отражать ту же проблему: Angular 2 render template после загрузки обещания с данными . Обратите внимание, что вопрос не имеет кода или принятого ответа в нем.

8 67

8 ответов:

пакета @angular/router имеет Resolve свойство для маршрутов. Таким образом, вы можете легко разрешить данные перед отображением представления маршрута.

см.:https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html

пример из документов на сегодня, 28 августа 2017 года:

class Backend {
  fetchTeam(id: string) {
    return 'someTeam';
  }
}

@Injectable()
class TeamResolver implements Resolve<Team> {
  constructor(private backend: Backend) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<any>|Promise<any>|any {
    return this.backend.fetchTeam(route.params.id);
  }
}

@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path: 'team/:id',
        component: TeamCmp,
        resolve: {
          team: TeamResolver
        }
      }
    ])
  ],
  providers: [TeamResolver]
})
class AppModule {}

теперь ваш маршрут не будет активирован, пока данные не будут разрешены и возвращены.

Доступ К Разрешенным Данным В Вашем Компонент

чтобы получить доступ к разрешенным данным из вашего компонента во время выполнения, Существует два метода. Поэтому в зависимости от ваших потребностей, вы можете использовать:

  1. route.snapshot.paramMap, который возвращает строку, или
  2. route.paramMap который возвращает наблюдаемый вы можете .subscribe() для.

пример:

  // the no-observable method
  this.dataYouResolved= this.route.snapshot.paramMap.get('id');
  // console.debug(this.licenseNumber);

  // or the observable method
  this.route.paramMap
     .subscribe((params: ParamMap) => {
        // console.log(params);
        this.dataYouResolved= params.get('id');
        return params.get('dataYouResolved');
        // return null
     });
  console.debug(this.dataYouResolved);

Я надеюсь, что помогает.

попробовать {{model?.person.name}} Это должно ждать модель, чтобы не быть undefined а потом выносят.

угловой 2 относится к этому ?. синтаксис как оператор Элвис. Ссылка на него в документации трудно найти, поэтому вот его копия в случае, если они изменят/переместят его:

Оператор Элвиса ( ?. ) и нулевые пути свойств

угловой оператор "Элвис" ( ?. ) беглый и удобный путь защитить против нуль и неопределенные значения в путях свойств. Вот он, защита от сбоя визуализации представления, если currentHero равно null.

The current hero's name is {{currentHero?.firstName}}

давайте подробно остановимся на проблеме и этом конкретном решении.

что происходит, когда следующее свойство заголовка с привязкой к данным равно null?

The title is {{ title }}

представление по-прежнему отображается, но отображаемое значение пустое; мы видим только "заголовок", после которого ничего нет. То есть разумное поведение. По крайней мере, приложение не падает.

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

The null hero's name is {{nullHero.firstName}}

JavaScript выдает ошибку null reference, а также Angular:

TypeError: Cannot read property 'firstName' of null in [null]

хуже того, весь вид исчезает.

мы могли бы утверждать, что это разумное поведение, если мы считал, что свойство hero никогда не должно быть null. Если он никогда не должен быть нулевым, и все же он равен нулю, мы сделали ошибку программирования, которая должна быть поймана и исправлена. Исключение-это правильно.

С другой стороны, нулевые значения в пути свойства могут быть в порядке время от времени, особенно когда мы знаем, что данные будут поступать в конечном итоге.

пока мы ждем данных, представление должно отображаться без жалоб, а путь к нулевому свойству должен отображаться как пустые так же, как название отеля.

к сожалению, наше приложение аварийно завершает работу, когда currentHero равен нулю.

мы могли бы кодировать вокруг этой проблемы с NgIf

<!--No hero, div not displayed, no error --> <div *ngIf="nullHero">The null hero's name is {{nullHero.firstName}}</div>

или мы могли бы попытаться связать части пути свойства с&&, зная, что выражение выручает, когда оно встречает первый null.

The null hero's name is {{nullHero && nullHero.firstName}}

эти подхода имеют свои достоинства, но они могут быть громоздким, особенно если путь длинный собственность. Представьте себе защиту от null где-то в длинном пути свойств, таких как a.b.c.d.

угловой оператор "Элвис" ( ?. ) является более быстрым и удобным способом защиты от нулей в путях свойств. Выражение выходит из строя, когда оно достигает первого нулевого значения. Дисплей пуст, но приложение продолжает катиться, и нет никаких ошибок.

<!-- No hero, no problem! --> The null hero's name is {{nullHero?.firstName}}

он отлично работает с длинными путями имущество:

a?.b?.c?.d

EDIT: угловая команда выпустила декоратор @Resolve. Он все еще нуждается в некотором разъяснении, в том, как это работает, но до тех пор я возьму здесь чей-то связанный ответ и предоставлю ссылки на другие источники:


EDIT: этот ответ работает только для Angular 2 BETA. Маршрутизатор не выпущен для Angular 2 RC на момент этого редактирования. Вместо этого при использовании Angular 2 RC замените ссылки на router С router-deprecated для продолжения использования бета-маршрутизатора.

Angular2-будущий способ реализовать это будет через @ Resolve decorator. До тогда ближайшим факсимиле является CanActivate декоратор компонентов, за Брэндона Робертса. смотрите https://github.com/angular/angular/issues/6611

хотя бета 0 не поддерживает предоставление разрешенных значений для компонента, это планируется, и есть также обходной путь, описанный здесь:Использование Resolve В Angular2 Routes

пример бета 1 можно найти здесь:http://run.plnkr.co/BAqA98lphi4rQZAd/#/resolved . Он использует очень подобный обходной путь, но чуть более точно использует RouteData объект, а не RouteParams.

@CanActivate((to) => {
    return new Promise((resolve) => {
        to.routeData.data.user = { name: 'John' }

кроме того, обратите внимание, что существует также пример обходного пути для доступа к вложенным/родительским маршрутам "разрешенные" значения, а также другие функции, которые вы ожидаете, если вы использовали 1.х уй-маршрутизатор.

Примечание вам также необходимо вручную ввести любые службы, необходимые для выполнения этого, так как иерархия угловых инжекторов в настоящее время недоступна в canactivate decorator. Просто импорт инжектора создаст новый экземпляр инжектора, без доступа к поставщикам из bootstrap(), поэтому вы, вероятно, захотите сохранить копию загрузочного инжектора на уровне приложения. Вторая ссылка Брэндона на этой странице является хорошей отправной точкой:https://github.com/angular/angular/issues/4112

установите локальное значение с помощью observer

...кроме того, не забудьте инициализировать значение с фиктивными данными, чтобы избежать uninitialized ошибки.

export class ModelService {
    constructor() {
      this.mode = new Model();

      this._http.get('/api/v1/cats')
      .map(res => res.json())
      .subscribe(
        json => {
          this.model = new Model(json);
        },
        error => console.log(error);
      );
    }
}

это предполагает модель, это модель данных, представляющая структуру ваших данных.

модель без параметров должна создать новый экземпляр со всеми инициализированными значениями (но пустыми). Таким образом, если шаблон отображается до получения данных, он не будет выдавать ошибку.

в идеале, если вы хотите сохранить данные, чтобы избежать ненужных http-запросов, которые вы должны поместить в объект, у которого есть свой собственный наблюдатель, на который вы можете подписаться.

реализовать routerOnActivate в своем @Component и верните свое обещание:

https://angular.io/docs/ts/latest/api/router/OnActivate-interface.html

EDIT: это явно не работает, хотя текущая документация может быть немного трудно интерпретировать по этой теме. Смотрите первый комментарий Брэндона здесь для получения дополнительной информации:https://github.com/angular/angular/issues/6611

изменить: соответствующая информация о в противном случае-обычно-точный сайт Auth0 не является правильным: https://auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in-depth/

EDIT: угловая команда планирует декоратор @Resolve для этой цели.

хорошее решение, которое я нашел-это сделать на UI что-то вроде:

<div *ngIf="vendorServicePricing && quantityPricing && service">
 ...Your page...
</div

когда: vendorServicePricing,quantityPricing и service загружаются страницы.

Я использую угловой 6 с универсальным дополнением Я специально прочитал ответы на второй вопрос. Но я еще не понял, в чем дело. У меня есть решатель, который вызывает и HttpClient XHR запрос и отправить в компонент и компонент на ngOnInit будет привязывать данные к представлению. Но проблема заключается в режиме просмотра источника, нет данных из ответа XHR, который отображается в представлении.

простое решение-инициализировать свойства объекта в init / constructor

кошки.капчане.самое смешное

Как только обещание будет разрешено, оно свяжет фактические значения.