#javascript #angular #typescript #mat-dialog
Вопрос:
У меня есть этот фрагмент кода, и мне нужны данные для динамического изменения. Поэтому я решил использовать для этого поток. Проблема в том, что он, похоже, копирует поток, и это не работает… Есть ли какой-нибудь способ передать его туда? Или, если это возможно, может быть, есть какое-то другое решение? Мы будем признательны за любые отзывы.
склад-стек-компонент.ts
import { CdkDragEnd, CdkDragStart } from '@angular/cdk/drag-drop'; import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { StackPalletsComponent } from '../modals/stack-pallets/stack-pallets.component'; import { MainServiceService } from '../services/main-service.service'; import { Observable, interval, BehaviorSubject, Subject } from 'rxjs'; import { Pallet } from '../models/pallet'; @Component({ selector: 'app-warehouse-stack', templateUrl: './warehouse-stack.component.html', styleUrls: ['./warehouse-stack.component.css'] }) export class WarehouseStackComponent implements OnInit{ @Input() warehouseStackID = null; @Input() name = null; @Input() position = null; @Input() set pallets(pallets:Pallet[]) { this.pallets$.next(pallets); } public pallets$:BehaviorSubjectlt;Pallet[]gt; = new BehaviorSubjectlt;Pallet[]gt;([]); public dialogRef: MatDialogReflt;StackPalletsComponentgt;; constructor(public mainService:MainServiceService,public dialog:MatDialog) { } public dragging:boolean; ngOnInit(): void { } updatePosition(e: CdkDragEnd) { this.mainService.updateStackPosition(this.warehouseStackID, e.source.getFreeDragPosition().x, e.source.getFreeDragPosition().y) } public handleDragStart(event: CdkDragStart): void { this.dragging = true; } openDialog() { this.dialogRef = this.dialog.open(StackPalletsComponent, { data: { warehouseStackID: this.warehouseStackID, pallets$: this.pallets$ } }); } handleClick(event: MouseEvent): void { if (this.dragging) { this.dragging = false; return } this.openDialog(); } }
штабель-поддоны-компонент.ts
import { Component, Inject, OnInit } from '@angular/core'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Pallet } from 'src/app/models/pallet'; import { MainServiceService } from 'src/app/services/main-service.service'; import { CreatePalletComponent } from '../create-pallet/create-pallet.component'; @Component({ selector: 'app-stack-pallets', templateUrl: './stack-pallets.component.html', styleUrls: ['./stack-pallets.component.css'] }) export class StackPalletsComponent implements OnInit { constructor(public mainService:MainServiceService, public dialogRef:MatDialogReflt;StackPalletsComponentgt;, public dialog:MatDialog,@Inject(MAT_DIALOG_DATA) public data: {warehouseStackID: number, pallets$:any}) { } ngOnInit(): void { } showCreationModal() { this.dialog.open(CreatePalletComponent, { data: { isStackPallet: true, warehouseStackID: this.data.warehouseStackID } }) } }
stack-pallets-component.html
lt;div class="pallets"gt; lt;app-pallet *ngFor="let pallet of this.data.pallets$|async" [position]="{x:pallet.positionX, y:pallet.positionY}" [pallet]="pallet"gt;lt;/app-palletgt; lt;div class="cubeRow"gt; lt;div class="cube"gt;lt;/divgt; lt;div class="cube"gt;lt;/divgt; lt;/divgt; lt;div class="cubeRow"gt; lt;div class="cube"gt;lt;/divgt; lt;div class="cube"gt;lt;/divgt; lt;/divgt; lt;div class="cubeRow"gt; lt;div class="cube"gt;lt;/divgt; lt;div class="cube"gt;lt;/divgt; lt;/divgt; lt;div class="buttons"gt; lt;button class="btn-floating btn-large waves-effect waves-light red" style="margin-top: 5px;" (click)="showCreationModal()"gt;lt;i class="material-icons"gt;addlt;/igt;lt;/buttongt; lt;/divgt; lt;/divgt;
Комментарии:
1. Можете ли вы вместо этого использовать диалоговую инъекцию ?
2. @francojay что ты имеешь в виду?
Ответ №1:
Доступ к потокам должен осуществляться из общей службы, а не из компонента. Причина, как правило, в том, что вы столкнетесь с циклическим импортом. Вместо того, чтобы вводить поток в следующий компонент, просто подпишитесь на поток, который находится в службе из этого компонента. Вы можете использовать pallets$.next(pallets)
любой компонент, в конструктор которого введена служба. Затем просто вставьте эту услугу в любой компонент, который вы хотите, и подпишитесь на нее.
Для управления памятью важно отказаться от подписки на ваши подписки. Мне нравится использовать для этого помощника (UntilDestroy); где он будет хранить подписки до уничтожения компонента.
Вот один из способов сделать это.
склад-стек.компонент.ts
@UntilDestroy({ checkProperties: true }) @Component({ selector: 'app-warehouse-stack', templateUrl: './warehouse-stack.component.html', styleUrls: ['./warehouse-stack.component.css'] }) export class WarehouseStackComponent implements OnInit, OnDestroy, OnChanges { @Input() set pallets(pallets:Pallet[]) {} constructor(warehouseService: WarehouseService) {} ngOnChanges(changes: SimpleChanges) { if (changes.pallets) { this.warehouseService.pallets$.next(changes.pallets.currentValue) } } openDialog() { this.dialogRef = this.dialog.open(StackPalletsComponent, { data: { warehouseStackID: this.warehouseStackID } }); } } ngOnDestroy() {}
склад.сервис.ts
@Injectable({ providedIn: 'root' }) export class WarehouseService { pallets$: BehaviorSubjectlt;Pallet[]gt; = new BehaviorSubjectlt;Pallet[]gt;([]) }
штабель-поддоны.компонент.ts
@UntilDestroy({ checkProperties: true }) @Component({ selector: 'app-stack-pallets', templateUrl: './stack-pallets.component.html', styleUrls: ['./stack-pallets.component.css'] }) export class StackPalletsComponent implements OnInit, OnDestroy { pallets: Pallet[] | [] palletsSub$: Subscription | undefined constructor(warehouseService: WarehouseService) { this.palletsSub$ = warehouseSevice.pallets$.subscribe((pallets) =gt; { this.pallets = pallets }) } } ngOnDestroy() {}
Комментарии:
1. Более простым способом передачи данных было бы использовать
this.warehouseService.pallets$.next(pallets)
их немедленно при изменении этих данных, вместо того, чтобы устанавливать их в @Input() и запускать ngOnChanges.