Получение данных из HTTP-запроса в конец шаблона

У меня есть служба, в которой создается HTTP-запрос для темы и поведения. Затем я получаю данные из службы на page.ts (в конструкторе), чтобы отобразить их в шаблоне.

Код, который я сделал, работает хорошо, но проблема в том, что шаблон «орет», что данные от субъекта еще не поступили. Поэтому это дает мне ошибку, если я хочу использовать его для инициализации элемента управления FORM или для отображения данных из массива.

PS: я пробовал с темой поведенческой темы, и у меня та же проблема. :( Я уверен, что делаю ошибку концепции.

Кто-нибудь знает, как получить данные до отображения шаблона?

Спасибо за вашу помощь

Код сервиса с Subject и с behaviorSubject:

const INTI_DATA = [];

@Injectable({
  providedIn: 'root'
})
export class FormStorageService {
  dbSubject = new Subject<any[]>();
  dbBSubject = new BehaviorSubject(INTI_DATA);
  data$: Observable<any> = this.dbBSubject.asObservable();

  private _URL: any = '../assets/DB-Test/data.json';


  private dbData: any[] = [];

  constructor(private http: HttpClient) {}


  getDBDataBehavior() {
    this.http.get<any[]>(this._URL).subscribe((response: any[]) => {
      const value = response['DB_DATA'];
      this.dbBSubject.next(value);
    }, error => {
      console.info('Error : ', error);
      alert(error.message);
    });
  }

  getDBData() {
    this.http.get<any[]>(this._URL).subscribe((response: any[]) => {
      const value = response['DB_DATA'];
      this.dbSubject.next(value);
    }, error => {
      console.info('Error : ', error);
      alert(error.message);
    });
  }
}

Page.TS (Form2Page) с вызовом темы

export class Form2Page implements OnInit, OnDestroy {
  obsSubscription: Subscription;
  public dbData: DataModel[] = [];

  itemsForm: FormGroup;

  constructor(private storageService: FormStorageService) {
    // Get data from DB
    this.storageService.getDBData();
    this.obsSubscription = this.storageService.dbSubject.subscribe(
      (value: any[]) => {
        this.dbData = value;
        console.info('Value in FORM2 : ', value);
        console.info('DB Data in FORM2 in subscribe : ', this.dbData);
      },
      error => {
        console.info('erreur', error);
      }
    );
    console.info('DB Data DB Data in FORM2 : ', this.dbData);
  }

  ngOnInit() {
    console.info('DB Data in FORM2 in ngOnInit : ', this.dbData);
  }

  ngOnDestroy() {
    this.obsSubscription.unsubscribe();
  }
}

Результат в консоли. Вы можете видеть, что dbData получает некоторые данные через некоторое время

DB Data DB Data in FORM2 :  []
form2.page.ts:46 DB Data in FORM2 in ngOnInit :  []
form2.page.ts:29 Value in FORM2 :  {ITEMS: Array(1)}
form2.page.ts:30 DB Data in FORM2 in subscribe :  {ITEMS: Array(1)}

Page.TS (Form3Page) с вызовом BehaviorSubject

export class Form3Page implements OnInit {
  obsBSubject$ = this.formStorage.data$;
  public dbData: any[] = [];

  constructor(private formStorage: FormStorageService) { 
    this.formStorage.getDBDataBehavior();
    this.obsBSubject$.subscribe(
      (value: any[]) => {
        this.dbData = value;
        console.info('Value in FORM3 : ', value);
        console.info('DB Data in FORM3 in subscribe : ', this.dbData);
      },
      error => {
        console.info('erreur', error);
      }
    );
    console.info('DB Data in FORM3 : ', this.dbData);
  }


  ngOnInit() {
    console.info('DB Data in FORM3 in ngOnInit : ', this.dbData);
  }

}

Результат в консоли. Вы можете видеть, что dbData получает некоторые данные через некоторое время

Value in FORM3 :  []
form3.page.ts:19 DB Data in FORM3 in subscribe :  []
form3.page.ts:25 DB Data in FORM3 :  []
form3.page.ts:30 DB Data in FORM3 in ngOnInit :  []

form3.page.ts:18 Value in FORM3 :  {ITEMS: Array(1)}
form3.page.ts:19 DB Data in FORM3 in subscribe :  {ITEMS: Array(1)}

Вы пытались добавить *ngIf = "data !== null && data !== undefined" в форму, используя данные?

kebbaben 27.06.2019 15:34

почему вы не подписаны на ваш сервис?

Ari Waisberg 27.06.2019 15:34

@ kebbaben нет, я еще не пробовал

JBD 27.06.2019 15:38

@Ari Waisberg Потому что я так учусь на курсах :( Может быть, есть другой способ, но я не знаю, как это сделать.

JBD 27.06.2019 15:39

@ kebbaben Ваше решение тоже работает очень хорошо !!! Спасибо большое!!! :)

JBD 04.07.2019 12:46
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
5
48
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать *ngIf, чтобы проверить, получили ли данные уже внешний интерфейс или нет.

*ngIf= = "data"

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

прежде всего вы должны получить данные от вызова метода службы в ngOninit, а не в конструкторе посмотрите по этой ссылке [Разница между конструктором и ngOnInit

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

для обходного решения, если вас не волнует производительность, используйте функцию setTimeOut, но лично я не предпочитаю это решение...

Есть несколько проблем, которые я заметил в вашем коде и логике.

  1. ngOnInit обычно используется для всех инициализаций/объявлений. Лучше избегать размещения логики в конструкторе. Конструктор следует использовать только для инициализации членов класса, но он не должен выполнять фактическую «работу». Поэтому я предлагаю вам перенести свою логику из конструктора в ваш ngOnInit()

  2. Вы не видите данные в своей консоли, потому что поток асинхронный. Таким образом, ваши журналы отображаются в консоли до того, как this.dbdata фактически получит значение.

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

Page.TS (Form3Page) с вызовом BehaviorSubject

export class Form3Page implements OnInit {
  obsBSubject$ = this.formStorage.data$;
  public dbData: any[] = [];

  constructor(
    private formStorage: FormStorageService
  ) { }

  ngOnInit() {
    this.formStorage.getDBDataBehavior();
    this.obsBSubject$.subscribe(
      (value: any[]) => {
        this.dbData = value;
        this.createForm();
        ...
      },
      error => {
        console.info('erreur', error);
      }
    );
  }

  createForm() {
    // Create form here
  }
}

Другие вопросы по теме