Как я могу передать объект поведения в данные MatDialog?

#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.