У меня есть служба, в которой создается 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)}
почему вы не подписаны на ваш сервис?
@ kebbaben нет, я еще не пробовал
@Ari Waisberg Потому что я так учусь на курсах :( Может быть, есть другой способ, но я не знаю, как это сделать.
@ kebbaben Ваше решение тоже работает очень хорошо !!! Спасибо большое!!! :)





Вы можете использовать *ngIf, чтобы проверить, получили ли данные уже внешний интерфейс или нет.
*ngIf= = "data"
Также вы можете проверить, больше ли длина нуля, с помощью другого div с *ngIf, чтобы сообщить, что данные уже здесь, НО без записей...
прежде всего вы должны получить данные от вызова метода службы в ngOninit, а не в конструкторе посмотрите по этой ссылке [Разница между конструктором и ngOnInit
затем, прежде чем отображать все данные в шаблоне, вы должны убедиться, что данные уже существуют, используя *ngIf
для обходного решения, если вас не волнует производительность, используйте функцию setTimeOut, но лично я не предпочитаю это решение...
Есть несколько проблем, которые я заметил в вашем коде и логике.
ngOnInit обычно используется для всех инициализаций/объявлений. Лучше избегать размещения логики в конструкторе. Конструктор следует использовать только для инициализации членов класса, но он не должен выполнять фактическую «работу». Поэтому я предлагаю вам перенести свою логику из конструктора в ваш ngOnInit()
Вы не видите данные в своей консоли, потому что поток асинхронный. Таким образом, ваши журналы отображаются в консоли до того, как this.dbdata фактически получит значение.
По причине, указанной в пункте 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
}
}
Вы пытались добавить
*ngIf = "data !== null && data !== undefined"в форму, используя данные?