CdkDragAndDrop Angular 可观察数据源正在重新加载我的组件
CdkDragAndDrop Angular observable datasource is reloading my component
我的问题是,每次我的订阅检测到新数据时,我的整个看板都会重新加载,并且列的滚动会返回到顶部。
这是我的 html:
<ng-container *ngIf="selectedBoard">
<div class="root">
<app-searcher> </app-searcher>
<div class="board">
<div class=" h1 ml-3 boardHeader"> {{selectedBoard.title}} </div>
<div class="board-wrapper">
<div style="overflow-x:scroll" class="board-columns scrollable-content" cdkScrollable >
<div cdkDropList
cdkDropListOrientation="horizontal" class="board-columns"
(cdkDropListDropped)="dropGrid($event)"
cdkDropListGroup
>
<div cdkDragLockAxis="x" class="board-column" *ngFor="let column of selectedBoard.columns; let columnIndex = index" cdkDrag [cdkDragDisabled]="readOnlyPermissions">
<div #colTitleEdit (click)="editColHeader(colTitleEdit,column)" class="column-title" cdkDragHandle>
<form class="form-input hidden">
<input #colHeaderTitleInput (click)="stopPropagation($event)"(keydown.esc)="editColHeaderConfirm(colHeaderTitleInput.value,colTitleEdit,column)" (keyup.enter)="editColHeaderConfirm(colHeaderTitleInput.value,colTitleEdit,column)" class="form-input" type="text" nbInput fullWidth fieldSize="medium" [(ngModel)]="column.headerText" name="listTitleEdit">
</form>
<span>{{ column.headerText }}</span>
<span *ngIf="writePermissions" nbContextMenuTag="column-options" nbContextMenuTrigger="focus" nbContextMenuPlacement="right" [nbContextMenu]="columnOptions" (click)="colOptions($event,column)" class="float-right colOptions">
<nb-icon class="edit-icon" icon="more-horizontal-outline"></nb-icon>
</span>
</div>
<div style="max-height:66vh; overflow-y:scroll" class="tasks-container " id="{{column._id}}" cdkDropList [cdkDropListData]="column.cards"
(cdkDropListDropped)="drop($event)">
<div class="task" (click)="dialogOpen(column._id,card._id,column.headerText)" *ngFor="let card of column.cards; let indexOfCard = index" cdkDrag [cdkDragStartDelay]="200" [cdkDragDisabled]="readOnlyPermissions" >
<span *ngIf="!currentlyEditing && writePermissions" (click)="editCardTitle($event,card,columnIndex,indexOfCard)" class="edit-btn float-right hide">
<nb-icon class="edit-icon" icon="edit-outline"></nb-icon>
</span>
<div class="task-header">
<app-labels (newLabels)="addLabel($event)" [labels]="card.labels"> </app-labels>
</div>
<div #cardOptionsMenu nbContextMenuTag="{{'card-options-'+columnIndex+'-'+indexOfCard}}" nbContextMenuTrigger="noop" nbContextMenuPlacement="right" [nbContextMenu]="cardOptions" id="{{'cardBody-' + columnIndex +'-'+indexOfCard}}" class="task-body">
<form *ngIf="currentlyEditing" class="form-input hidden">
<textarea (keydown.esc)="cancelEditCard($event,card,columnIndex,indexOfCard)" (clickOutside)="clickOutsideCancel(card,columnIndex,indexOfCard)" class="cardEdit" (click)="stopPropagation($event)" id="{{'cardTitle-'+columnIndex+'-'+indexOfCard}}" nbInput fullWidth fieldSize="large" name="cardTitle"> </textarea>
<div class="d-flex align-items-center pb-2 pt-2">
<button type="submit" nbButton status="success" size="small" class="submit-btn shadow-3d float-left" (click)="editCardConfirm($event)"> <nb-icon icon="checkmark-outline"></nb-icon>Guardar</button>
<span (click)="cancelEditCard($event,card,columnIndex,indexOfCard)" class="float-left ml-2 cancelNewCard"> <nb-icon icon="close-outline"> </nb-icon> </span>
</div>
</form>
<span> {{ card.title }} </span>
</div>
<div class="task-footer">
<span style="font-size:12px; color:#5e6c84;" *ngIf="card.attachments > 0"> <nb-icon class="float-left" [config]="{icon: 'attach-outline', options: {'icon-font-size': '16px'}}"> </nb-icon> {{card.attachments}} </span>
<span *ngIf="(card.cardInfo && card.cardInfo.FechaEntrega && card.cardInfo.FechaEntrega.length>9) || card.expirationDate" class="info-badge" text="20 may"> <nb-icon icon="clock-outline"> </nb-icon> {{card.cardInfo.FechaPedido | date:'dd MMM' }}</span>
</div>
</div>
</div>
<div class="column-footer mt-2 pb-2">
<button *ngIf="writePermissions" id="{{'addCardButton-' + columnIndex}}" nbButton status="info" size="small" class="btn-shadow-3d shadow-3d " (click)="showTitleInput(columnIndex)"> <nb-icon icon="plus"></nb-icon>Añadir una tarjeta</button>
<div class="row">
<div class="newCardInput col-12" id="{{'Title-' + columnIndex}}" style="display:none;">
<form>
<input (keydown.esc)="cancelNewCard()" #cardTitleInput class="form-input" type="text" id="{{'cardTitle-' + columnIndex}}" nbInput fullWidth fieldSize="medium" placeholder="Título de la tarjeta" name="title">
<div class="d-flex align-items-center pb-2 pt-2">
<button type="submit" nbButton status="success" size="small" class="submit-btn shadow-3d float-left" (click)="addNewCard(cardTitleInput.value,columnIndex)"> <nb-icon icon="checkmark-outline"></nb-icon>Ok</button>
<span (click)="cancelNewCard()" class="float-left ml-2 cancelNewCard"> <nb-icon icon="close-outline"> </nb-icon> </span>
</div>
</form>
</div>
</div>
</div>
</div>
<div *ngIf="writePermissions" #newColumnInput (click)="addColumn()" class="add-new-col" >
<form class="form-input hidden">
<input #colTitleInput class="form-input" type="text" nbInput fullWidth fieldSize="medium" placeholder="Título de la lista" name="listTitle">
<div class="d-flex align-items-center pb-2 pt-2">
<button type="submit" nbButton status="success" size="small" class="submit-btn shadow-3d float-left" (click)="addColumn(colTitleInput.value)"> <nb-icon icon="checkmark-outline"></nb-icon>Aceptar</button>
<span (click)="cancelColumnAdd($event)" class="float-left ml-2 cancelNewCard"> <nb-icon icon="close-outline"> </nb-icon> </span>
</div>
</form>
<h3> <nb-icon icon="plus-outline"></nb-icon> Añadir otra lista </h3>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-container>
在我的 component.ts 上,我有一个从后端侦听套接字的方法。
this.socketService.listenFromClient('kanbanToClient').subscribe((res:any) => {
//con.sole.log(res)
this.selectedBoard.columns = new Board(res).columns;
this.kanbanService.currentBoard = this.selectedBoard;
//con.sole.log(this.selectedBoard)
})
我需要滚动条保持在同一位置并阻止标签的动画。因为那些动画也是因为“重新加载”
正如@Jason White 所说
Try adding a trackBy function to your ngfor loops and track by a
unique I'd.
我这样做了,问题解决了。非常感谢。
我的问题是,每次我的订阅检测到新数据时,我的整个看板都会重新加载,并且列的滚动会返回到顶部。
这是我的 html:
<ng-container *ngIf="selectedBoard">
<div class="root">
<app-searcher> </app-searcher>
<div class="board">
<div class=" h1 ml-3 boardHeader"> {{selectedBoard.title}} </div>
<div class="board-wrapper">
<div style="overflow-x:scroll" class="board-columns scrollable-content" cdkScrollable >
<div cdkDropList
cdkDropListOrientation="horizontal" class="board-columns"
(cdkDropListDropped)="dropGrid($event)"
cdkDropListGroup
>
<div cdkDragLockAxis="x" class="board-column" *ngFor="let column of selectedBoard.columns; let columnIndex = index" cdkDrag [cdkDragDisabled]="readOnlyPermissions">
<div #colTitleEdit (click)="editColHeader(colTitleEdit,column)" class="column-title" cdkDragHandle>
<form class="form-input hidden">
<input #colHeaderTitleInput (click)="stopPropagation($event)"(keydown.esc)="editColHeaderConfirm(colHeaderTitleInput.value,colTitleEdit,column)" (keyup.enter)="editColHeaderConfirm(colHeaderTitleInput.value,colTitleEdit,column)" class="form-input" type="text" nbInput fullWidth fieldSize="medium" [(ngModel)]="column.headerText" name="listTitleEdit">
</form>
<span>{{ column.headerText }}</span>
<span *ngIf="writePermissions" nbContextMenuTag="column-options" nbContextMenuTrigger="focus" nbContextMenuPlacement="right" [nbContextMenu]="columnOptions" (click)="colOptions($event,column)" class="float-right colOptions">
<nb-icon class="edit-icon" icon="more-horizontal-outline"></nb-icon>
</span>
</div>
<div style="max-height:66vh; overflow-y:scroll" class="tasks-container " id="{{column._id}}" cdkDropList [cdkDropListData]="column.cards"
(cdkDropListDropped)="drop($event)">
<div class="task" (click)="dialogOpen(column._id,card._id,column.headerText)" *ngFor="let card of column.cards; let indexOfCard = index" cdkDrag [cdkDragStartDelay]="200" [cdkDragDisabled]="readOnlyPermissions" >
<span *ngIf="!currentlyEditing && writePermissions" (click)="editCardTitle($event,card,columnIndex,indexOfCard)" class="edit-btn float-right hide">
<nb-icon class="edit-icon" icon="edit-outline"></nb-icon>
</span>
<div class="task-header">
<app-labels (newLabels)="addLabel($event)" [labels]="card.labels"> </app-labels>
</div>
<div #cardOptionsMenu nbContextMenuTag="{{'card-options-'+columnIndex+'-'+indexOfCard}}" nbContextMenuTrigger="noop" nbContextMenuPlacement="right" [nbContextMenu]="cardOptions" id="{{'cardBody-' + columnIndex +'-'+indexOfCard}}" class="task-body">
<form *ngIf="currentlyEditing" class="form-input hidden">
<textarea (keydown.esc)="cancelEditCard($event,card,columnIndex,indexOfCard)" (clickOutside)="clickOutsideCancel(card,columnIndex,indexOfCard)" class="cardEdit" (click)="stopPropagation($event)" id="{{'cardTitle-'+columnIndex+'-'+indexOfCard}}" nbInput fullWidth fieldSize="large" name="cardTitle"> </textarea>
<div class="d-flex align-items-center pb-2 pt-2">
<button type="submit" nbButton status="success" size="small" class="submit-btn shadow-3d float-left" (click)="editCardConfirm($event)"> <nb-icon icon="checkmark-outline"></nb-icon>Guardar</button>
<span (click)="cancelEditCard($event,card,columnIndex,indexOfCard)" class="float-left ml-2 cancelNewCard"> <nb-icon icon="close-outline"> </nb-icon> </span>
</div>
</form>
<span> {{ card.title }} </span>
</div>
<div class="task-footer">
<span style="font-size:12px; color:#5e6c84;" *ngIf="card.attachments > 0"> <nb-icon class="float-left" [config]="{icon: 'attach-outline', options: {'icon-font-size': '16px'}}"> </nb-icon> {{card.attachments}} </span>
<span *ngIf="(card.cardInfo && card.cardInfo.FechaEntrega && card.cardInfo.FechaEntrega.length>9) || card.expirationDate" class="info-badge" text="20 may"> <nb-icon icon="clock-outline"> </nb-icon> {{card.cardInfo.FechaPedido | date:'dd MMM' }}</span>
</div>
</div>
</div>
<div class="column-footer mt-2 pb-2">
<button *ngIf="writePermissions" id="{{'addCardButton-' + columnIndex}}" nbButton status="info" size="small" class="btn-shadow-3d shadow-3d " (click)="showTitleInput(columnIndex)"> <nb-icon icon="plus"></nb-icon>Añadir una tarjeta</button>
<div class="row">
<div class="newCardInput col-12" id="{{'Title-' + columnIndex}}" style="display:none;">
<form>
<input (keydown.esc)="cancelNewCard()" #cardTitleInput class="form-input" type="text" id="{{'cardTitle-' + columnIndex}}" nbInput fullWidth fieldSize="medium" placeholder="Título de la tarjeta" name="title">
<div class="d-flex align-items-center pb-2 pt-2">
<button type="submit" nbButton status="success" size="small" class="submit-btn shadow-3d float-left" (click)="addNewCard(cardTitleInput.value,columnIndex)"> <nb-icon icon="checkmark-outline"></nb-icon>Ok</button>
<span (click)="cancelNewCard()" class="float-left ml-2 cancelNewCard"> <nb-icon icon="close-outline"> </nb-icon> </span>
</div>
</form>
</div>
</div>
</div>
</div>
<div *ngIf="writePermissions" #newColumnInput (click)="addColumn()" class="add-new-col" >
<form class="form-input hidden">
<input #colTitleInput class="form-input" type="text" nbInput fullWidth fieldSize="medium" placeholder="Título de la lista" name="listTitle">
<div class="d-flex align-items-center pb-2 pt-2">
<button type="submit" nbButton status="success" size="small" class="submit-btn shadow-3d float-left" (click)="addColumn(colTitleInput.value)"> <nb-icon icon="checkmark-outline"></nb-icon>Aceptar</button>
<span (click)="cancelColumnAdd($event)" class="float-left ml-2 cancelNewCard"> <nb-icon icon="close-outline"> </nb-icon> </span>
</div>
</form>
<h3> <nb-icon icon="plus-outline"></nb-icon> Añadir otra lista </h3>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-container>
在我的 component.ts 上,我有一个从后端侦听套接字的方法。
this.socketService.listenFromClient('kanbanToClient').subscribe((res:any) => {
//con.sole.log(res)
this.selectedBoard.columns = new Board(res).columns;
this.kanbanService.currentBoard = this.selectedBoard;
//con.sole.log(this.selectedBoard)
})
我需要滚动条保持在同一位置并阻止标签的动画。因为那些动画也是因为“重新加载”
正如@Jason White 所说
Try adding a trackBy function to your ngfor loops and track by a unique I'd.
我这样做了,问题解决了。非常感谢。