簡體   English   中英

Angular - 動態添加/刪除單個組件的多個實例而無需刷新頁面來更新視圖

[英]Angular - Dynamically adding / removing multiple instances of a single component without having to refresh the page to update the view

這是我第三次嘗試提出這個問題。

這個問題會很長,因為我看不出有什么辦法可以縮短它。

客觀的

我想要做的是有一個簡單的網絡應用程序,它有一個 header(我創建為HeaderComponent )和按鈕,一個頁面(我創建為LiveSummaryComponent )將顯示一個的多個實例將顯示不同數據的組件(我將其創建為StatusBoxComponent )。

header 將有一個按鈕,可以打開一個模式對話框(我將其創建為AddStatusBoxComponent ),其中有一個表單和一個提交按鈕。 提交表單時,表單數據將作為 map 數據結構保存到瀏覽器本地存儲中,而且此時我想創建一個StatusBoxComponent實例,它將顯示在LiveSummaryComponent頁面上。

然后,該特定StatusBoxComponent實例應檢索本地存儲中的值以顯示唯一值。 我還希望能夠通過單擊StatusBoxComponent的每個實例上的按鈕以及編輯按鈕來刪除StatusBoxComponent實例。

理想情況下,我還希望能夠在每次添加、編輯或刪除新的StatusBoxComponent實例時不必刷新頁面來更新LiveSummaryComponent頁面。

目前如何運作

多虧了我前段時間對這個問題的回答,我現在確實可以部分工作,但它有局限性,因為我無法找到一種方法來刪除和編輯StatusBoxComponent的每個實例中的信息。 我只能在提交表單時添加。 此外,每次添加新的StatusBoxComponent實例時,您都必須刷新頁面以更新LiveSummaryComponent頁面,這很煩人。

其工作方式是,當提交AddStatusBoxComponent表單時,它僅將表單數據放入本地存儲中的 map 數據結構中,並賦予唯一的名稱/鍵。 StatusBoxComponent實例的創建方式是在 LiveSummaryComponent 的ngInit() function 中迭代所有本地存儲 map 數據結構並傳遞給名為myConfigs的數組。 然后在名為DynamicStatusBoxDirective的指令中訪問myConfigs數組中的每個 Map,該指令實際上使用ComponentFactoryResolver創建StatusBoxComponent的實例。 然后,該特定StatusBoxComponent將使用傳入的配置變量中的數據填充,該config變量來自LiveSummaryComponent中的myConfigs數組。

這種做法意味着DynamicStatusBoxDirective只需加載與本地存儲映射一樣多的StatusBoxComponent實例。 它在ngInit() function 中執行此操作,因此它會立即加載所有內容,而不是在單擊按鈕時動態添加,這也不理想。

LiveSummaryComponent ts 代碼:

import { Component, OnInit,} from '@angular/core';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-live-summary',
  templateUrl: './live-summary.component.html',
  styleUrls: ['./live-summary.component.css']
})
export class LiveSummaryComponent implements OnInit 
{
  subscription!: Subscription;
  myConfigs: any[] = [];
  localStorageKeys: string[] = ['Old', 'New', 'Current', 'Test']

  constructor() { }

  ngOnInit(): void 
  {
    for (var key of this.localStorageKeys) // iterates though each type of device
      for(let i = 1; i < 5; i++) // for each of those device types 
        if (localStorage.getItem(key+i+'Topics') != null) // if the device + topics string is not null in local storage
          this.myConfigs.push(new Map(JSON.parse(localStorage.getItem(key+i+'Topics')!))) 
        else
          console.log(key+i + ' currently not deployed');
  }
 }

LiveSummaryComponent html 代碼:

<div class='status-box-container'>
    <ng-container *ngFor="let config of myConfigs; let i=index" appDynamicStatusBox [config]="config"></ng-container>
</div>

DynamicStatusBoxDirective ts代碼:

import { ComponentFactoryResolver, ComponentRef, Directive, Input, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
import { StatusBoxComponent } from '../components/status-box/status-box.component';

@Directive({selector: '[appDynamicStatusBox]'})

export class DynamicStatusBoxDirective implements OnInit, OnDestroy 
{
  @Input() config: any;
  componentRef!: ComponentRef<StatusBoxComponent>;

  constructor(private resolver: ComponentFactoryResolver, public viewContainerRef: ViewContainerRef) {}

  ngOnInit(): void 
  {
    const factory = this.resolver.resolveComponentFactory(StatusBoxComponent); 
    this.viewContainerRef.clear(); 
    this.componentRef = this.viewContainerRef.createComponent(factory); 

    // set each  StatusBoxComponent vars with values from myConfig
    this.componentRef.instance.deviceId = this.config.get('deviceId')
    this.componentRef.instance.infoExample1 = this.config.get('infoExample1')
    this.componentRef.instance. infoExample2 = this.config.get('infoExample2')
    this.componentRef.instance. infoExample3 = this.config.get('infoExample3')

  }
 }

我嘗試過的是在每個 StatusBoxComponent 實例上獲取刪除/編輯功能

我發現這段代碼使您能夠添加和刪除組件的實例,但它有一個限制,如果您不按順序刪除組件,它會弄亂它使用的索引 ID 系統。 這意味着您最終可能會得到兩個具有相同 ID 的組件實例。 為了解決這個問題,我寧願使用在每個本地存儲 Map 中設置的deviceID值(它是一個字符串)來標識我的StatusBoxComponent的每個實例而不是索引。 (雖然我不確定這將如何工作)。

此代碼的另一個問題是調用createComponnent()的按鈕都在一個組件中。 在我的例子中,我想讓我的LiveSummaryComponent定義createComponent() function ,它與我當前的DynamicStatusBoxDirective 但是能夠從AddStatusBoxComponent中的表單提交按鈕調用/訪問createComponent() 顯然它們是兩個完全不同的組件。 從這個和我問的這個問題可以看出,在 LiveSummaryComponent 之外訪問createComponent() function 會給我錯誤。 不幸的是,后一個問題的解決方案我無法開始工作。

結論

我不確定我是否應該堅持使用DynamicStatusBoxDirective的原始方法,或者我是否應該嘗試讓我鏈接的示例代碼工作以實現我的目標。 或者我應該做些不同的事情嗎?

當單擊組件上的刪除按鈕時,似乎也很難知道要刪除哪個StatusBoxComponent實例。 本地存儲中的每個 map 數據結構都有一個我想使用的字符串deviceID值。 但我不知道如何將該deviceID字符串與特定的StatusBoxComponent實例相關聯。

我完全堅持這一點。

我希望我想要達到的目標至少是清楚的。 請點擊我的其他問題的鏈接,因為這將提供更多背景信息。 由於敏感信息,創建我的代碼的 stackblitz 將非常困難。

謝謝。

您可以使用服務從 localStorage 和帶有當前值數組的 stream 存儲/讀取數據。

    @Injectable()
    export class SomeService { 
        constructor() {
            this._initStream();        
        }
               
        //your stream with statuses
        public statuses$ = new BehaviorSubject([]);

        private _initStream(){
            // get data from localStorage
            // transform Map to Array
            this.statuses$.next(transformedDataToArray);
        } 
        
        // add status, use it in your modal    
        addStatus(props) {
           ...your logic to add
           this._updateDataInLocalStorage();
           this._updateStream();
        }
        // use it in your StatusBoxComponent    
        removeStatus() {
            ...your logic to remove
            this._updateDataInLocalStorage();
            this._updateStream();
        }
        // use it in your StatusBoxComponent  
        updateStatus() {
            ...your logic to remove
            this._updateDataInLocalStorage();
            this._updateStream();
        }
        // set current value to stream
        _updateStream() {
            const statuses = localStorage.getItem();
            this.statuses$.next(statuses)
        }
        // update data in localStroage
        _updateDataInLocalStorage() {
            ...some logic here
        }

LiveSummaryComponent html 文件

<app-status-box *ngFor="let status of SomeService.statuses$ | async; let i=index" [props]="status" [index]="index"></app-status-box>

把它想象成你有一個簡單的狀態數組和一個唯一的 id(映射鍵)並使用它。 在方法中使用本地存儲的所有工作是將數組轉換為 Map 並保存到本地存儲,反之亦然 - 將 Map 從本地存儲轉換為數組以顯示您的狀態。 *ngFor將完成顯示組件的所有工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM