iT邦幫忙

2024 iThome 鐵人賽

DAY 29
1
佛心分享-SideProject30

收納規劃APP系列 第 29

Day29:收納物品的增刪改查

  • 分享至 

  • xImage
  •  

串接階段發現最常報錯的就是前後端命名不一樣,就算我都寫好型別了,不知道有沒有更智慧的防呆辦法可以處理,而且有的時候串接起來才發現API開的跟畫面需求有點不一樣,一遍就全部開對而且理解業務邏輯的人真是老江湖啊,就算需求是我自己開的,我都需要微調了

以下是程式碼,因為有串DB但是還沒加驗證,所以沒有放上 stackblitz

父層

import { Component, ElementRef, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
import { NzModalService } from 'ng-zorro-antd/modal';
import { CRUD, EditType } from 'src/app/feature/enum/furniture.enum';
import { Furniture, StorageItem } from 'src/app/feature/interface/furniture.interface';
import { FurnitureModalComponent } from 'src/app/feature/modal/furniture-modal/furniture-modal.component';
import { StorageModalComponent } from 'src/app/feature/modal/storage-modal/storage-modal.component';
import { StorageService } from './service/storage.service';

@Component({
  selector: 'app-day18',
  templateUrl: './day18.component.html',
  styleUrls: ['./day18.component.scss']
})
export class Day18Component implements OnInit {
...
  onPopoverButtonClick(editType: EditType,) {
    switch (editType) {
      case EditType.furniture:
        this.isPopoverVisible = false;
        this.furnitureModal(this.furnitureSetting);

        break;
      case EditType.storage:
        this.isPopoverVisible = false;
        // this.storageService.getStorageItemsByFurnitureId(this.furnitureSetting._id).subscribe((res)=>{
          
          this.storageModal(this.furnitureSetting._id);
        // })
        break;

      default:
        break;
    }
  }

...
  private storageModal(furnitureId:string): void {
    this.modal.create({
      // nzTitle: tplTitle,
      nzContent: StorageModalComponent,
      nzFooter: null,
      nzWidth: '95vw',
      // nzMaskClosable: false,
      // nzClosable: false,
      nzData: {
        // listOfData: itemList,
        furnitureId
      },
      nzOnOk: () => console.log('Click ok')
    });
  }
...
}

收納物品設定彈窗

<app-default-modal [name]="'收納明細'">
    <div class="text-end py-2">
        <button nz-button style="width: 120px;" (click)="add()" [disabled]="isEditing"nzType="primary"><span nz-icon nzType="plus"
                nzTheme="outline"></span></button>
    </div>
    <nz-table #editRowTable nzBordered [nzData]="listOfData" nzTableLayout="fixed">
        <thead>
            <tr>
                <th nzWidth="20%">物品名</th>
                <th nzWidth="8%">數量</th>
                <th nzWidth="15%">單位</th>
                <th nzWidth="40%">備註</th>
                <th nzWidth="15%">Action</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let data of editRowTable.data">
                <ng-container *ngIf="!editCache[data._id].edit; else editTemplate">
                    <td>{{ data.name }}</td>
                    <td>{{ data.quantity }}</td>
                    <td>{{ data.unit }}</td>
                    <td>{{ data.note }}</td>
                    <td>
                        <div class="d-flex justify-content-around">
                            <span nz-icon nzType="edit" nzTheme="outline" (click)="startEdit(data._id)" [class.disabled]="isEditing"></span>
                            <span nz-icon nzType="delete" nzTheme="outline" (click)="deleteRow(data._id)" [class.disabled]="isEditing"></span>
                        </div>
                    </td>
                </ng-container>
                <ng-template #editTemplate>
                    <td><input type="text" nz-input [(ngModel)]="editCache[data._id].data.name" /></td>
                    <td><input type="text" nz-input [(ngModel)]="editCache[data._id].data.quantity" /></td>
                    <td><input type="text" nz-input [(ngModel)]="editCache[data._id].data.unit" /></td>
                    <td><input type="text" nz-input [(ngModel)]="editCache[data._id].data.note" /></td>
                    <td>
                        <div class="d-flex justify-content-around">
                            <a nz-popconfirm nzPopconfirmTitle="Sure to save?"
                                (nzOnConfirm)="saveEdit(data._id,data.isNew)" class="save">Save</a>
                            <a nz-popconfirm nzPopconfirmTitle="Sure to cancel?"
                                (nzOnConfirm)="cancelEdit(data._id)">Cancel</a>
                        </div>
                    </td>
                </ng-template>
            </tr>
        </tbody>
    </nz-table>
</app-default-modal>
import { Component, inject } from '@angular/core';
import { NZ_MODAL_DATA, NzModalRef } from 'ng-zorro-antd/modal';
import { StorageItem } from '../../interface/furniture.interface';
import { StorageService } from 'src/app/page/day18/service/storage.service';

@Component({
  selector: 'app-storage-modal',
  templateUrl: './storage-modal.component.html',
  styleUrls: ['./storage-modal.component.scss']
})
export class StorageModalComponent {
  listOfData: StorageItem[] = [];
  readonly #modal = inject(NzModalRef);
  readonly nzModalData: { furnitureId: string } = inject(NZ_MODAL_DATA);
  editCache: { [key: string]: { edit: boolean; data: StorageItem } } = {};
  isEditing: boolean = false; // 新增此行

  constructor(
    private storageService: StorageService
  ) {
    this.getStorageItemList();
    }

  ngOnInit(): void {
  }

  private updateEditCache(): void {
    this.listOfData.forEach(item => {
      this.editCache[item._id] = {
        edit: false,
        data: { ...item }
      };
    });
  }

  private getStorageItemList() {
    this.storageService.getStorageItemsByFurnitureId(this.nzModalData.furnitureId)
      .subscribe((res) => {
        if (res) {
          this.listOfData = res;
          this.updateEditCache();
        }
      })
  }

  add() {
    if (this.isEditing) return; // 如果正在編輯,則不允許新增

    this.listOfData = [
      ...this.listOfData,
      {
        _id: this.listOfData.length.toString(),
        name: '', quantity: 0, unit: '個', note: '',
        parentItemId: this.nzModalData.furnitureId,
        furnitureId: this.nzModalData.furnitureId,
        isNew: true,
      }
    ]
    this.updateEditCache();
    this.startEdit((this.listOfData.length - 1).toString());
  }

  startEdit(id: string): void {
    if (this.isEditing) return; // 如果正在編輯,則不允許新的編輯
    this.isEditing = true; // 設置編輯狀態
    this.editCache[id].edit = true;
  }

  cancelEdit(id: string): void {
    const index = this.listOfData.findIndex(item => item._id === id);
    this.editCache[id] = {
      data: { ...this.listOfData[index] },
      edit: false
    };
    this.isEditing = false; // 重置編輯狀態
  }

  deleteRow(id: string): void {
    if (this.isEditing) return; // 如果正在編輯,則不允許刪除
    this.storageService.deleteStorageItem(id).subscribe(() => {
      this.getStorageItemList();
    });
  }

  saveEdit(id: string, isNew: boolean): void {
    if (isNew) {
      const data: any = this.editCache[id].data;
      delete data._id;
      delete data.isNew;
      this.storageService.createStorageItem(this.editCache[id].data).subscribe(() => {
        this.getStorageItemList();
        this.isEditing = false; // 重置編輯狀態
      });
    } else {
      const data: any = this.editCache[id].data;
      delete data.isNew;
      this.storageService.updateStorageItem(id, this.editCache[id].data).subscribe(() => {
        this.getStorageItemList();
        this.isEditing = false; // 重置編輯狀態
      });
    }
  }
}

.disabled {
    opacity: 0.5;
    pointer-events: none;
}

上一篇
Day28:家具的增加、刪除
下一篇
Day30:完賽
系列文
收納規劃APP32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言