компонент (пусть будет компонент "Х") редактирования сущности (сущность - объект с кучей разных полей), эта сущность ранее приходила в компонент Х через @Input, причем если правильно помню, как readOnly (насколько я понял - потому что это строка из обсервабл массива), поэтому я его клонировал и дальше изменял, путем двустороннего байндинга полей этой сущности к селектбоксам компонента Х.
Затем потребовалось приделать к этому компоненту Х роутинг, поэтому возник вопрос как передавать туда данные. Я стал передавать uid сущности через url params, создал в компоненте переменную BehaviorSubject и из компонента запрашиваю по uid объект для редактирования, в подписке на запрос присваиваю BehaviorSubject новое значение (объект для будущего редактирования). Затем я в каждом селектбоксе компонента X отображаю данные этой сущности через односторонний байндинг с асинк пайпом (двусторонний тут уже не работает), и с помощью ивентов изменения селектбоксов получаю текущее значение BehaviorSubject через метод getValue(), редактирую в нем данные и сохраняю в BehaviorSubject, которые потом улетает на сервер put запросом.
<dx-select-box
[value]="(currentTicket$ | async).type"
(valueChange)="changeTicketType($event)"
>
</dx-select-box>
changeTicketType (ticketType: TicketType): void {
let currentTicket = this.currentTicket$.getValue()
currentTicket.type = ticketType
this.currentTicket$.next(currentTicket)
}
Вроде все работает, однако я тут прочитал, что использовать BehaviorSubject.getValue() - нужно в крайних случаях, как тогда можно изменить мою концепцию, чтобы было более корректно?
"Important note from the author of RxJS 5: Using getValue() is a HUGE red flag you're doing something wrong. It's there as an escape hatch. Generally everything you do with RxJS should be declarative. getValue() is imperative. If you're using getValue(), there's a 99.9% chance you're doing something wrong or weird."
Банально можно достать value из асинк пайпа [lalala] = "(value$ | async as myValue).type" (change)="callback($event, myValue)" Но: 1) getValue будет костылем для серьезной асинхронной логики, а в использовании его для хранения внутреннего состояния проблемы не вижу, тут почти негде накосячить 2) возможно, вам удастся вообще не использовать bSubject, у меня бывали такие случаи, смог переделать на обычную проперти
И еще, плохая практика кидать один и тот же объект в сабжект, вы же не знаете, может у подписчика distinctUntilChanged стоит
какие вообще есть способы обойтись без асинк пайпов при асинхронном запросе данных в компоненте?
Покажите, как вы данные получаете
Например можно просто не использовать асинк пайпы. Использовать fetch, HttpClient и всё такое
ngOnInit (): void { this.loading$.next(true) this.subs.sink = this.ticketsService.fetchTicketByUID(this.ticketUID) .subscribe({ next: ticket => { this.loading$.next(false) this.currentTicket$.next(ticket) }, error: err => { console.log(err) this.loading$.next(false) } }) this.subs.sink = this.ticketTypesService.fetchTicketTypes() .subscribe(res => this.ticketTypes.next(res)) }
async pipe норм, можно сделать просто подписки по-другому readonly data$ = combineLatest({ticket: this.ticketsService.fetchTicketByUID(this.ticketUID), ticketType: this.ticketTypesService.fetchTicketTypes()}); и в темплейте <ng-container *ngIf="data$ | async as data"> <my-component [value]="data.ticket"></> </>
httpClient я и так вроде использую для запросов, но кажется проблема не в том, как запросить данные у сервера, а в том, чтобы их отобразить в тот момент, когда они придут, т.к. при OnPush ангуляр перестает искать изменения в приложении от каждого чиха и его нужно пинать, либо я чего-то не понял)
Ну просто объект с данными привяжите и посмотрите сработает ли changeDetection
я уже пробовал сперва так сделать, у меня отображался полупустой компонент со статичными данными
Обсуждают сегодня