在 Angular HTTP 请求动态填充表行中的子表后,在当前页面中找不到节点

Node cannot be found in the current page after Angular HTTP request for dynamically filling a subtable within a table row

提问人:MyNameIsJeff 提问时间:9/12/2023 更新时间:9/12/2023 访问量:69

问:

我的项目旨在加载一个包含每个进程的进程和子进程的表。为了实现这一点,对于可扩展的子进程行,我想到了以下几点:偶数索引行是进程,奇数索引行是包含另一个表的表行,上面进程的子进程对应于它们。

问题是我实现了一个弹出窗口,当单击子进程子表的子进程行上的复选框时,该弹出窗口应该会打开。

通过本地数据,它可以完美地工作,但是通过HTTP,当我在开发工具中使用“检查”命令选择它时,它会说“在当前页面中找不到节点”。此外,它知道我有 HTML,但即使在检查了首先加载进程之后,我也无法使用它,然后加载了该进程的子进程(我确保在隐藏行的第一次扩展时只加载一次),使用 sessionStorage 轻松检索它们无论是 DOM 还是组件。

toggledIndex 变量是通过 router-outlet 从另一个组件接收的要打开的索引。ng-container *ngIf 对此索引的检查用于检查是否对该行进行了特定的 HTTP 调用,toggledIndex 是组件初始化时的第一个,因此是一种特殊情况。

进程菜单.组件.html:

<div id="content">
    <ng-container *ngIf="processesLoaded | async">
        <table>
            <ng-container *ngFor="let process of processes; let i=index">
                <tr style="cursor: pointer">
                    <td class="processName"  (click)="toggleExpanded($event,i)">
                        <i [ngClass]="i===toggledIndex ? 'fa fa-chevron-down' : 'fa fa-chevron-right'"></i>
                        <p>{{process.name}}</p>
                    </td>
                    <td class="processCheckbox">
                            <div>&nbsp;</div>
                    </td>
                    <td 
                        [ngClass]="i===toggledIndex ? 'procHead black' : 'procHead white'"
                        (click)="toggleExpanded($event,i)">
                            Description of the requirement
                    </td>
                    <td 
                        [ngClass]="i===toggledIndex ? 'procHead black' : 'procHead white'"
                        (click)="toggleExpanded($event,i)">
                            Overall intent of the requirement
                    </td>
                </tr>
                <ng-container *ngIf="i===toggledIndex">
                    <tr style="width: 100%; height: fit-content;">
                        <td colspan="4" style="height: fit-content; padding: 0 20px 0 20px;">
                            <table class="subprocessesTable">
                                <ng-container *ngIf="get(i)">
                                    <ng-container *ngFor="let subprocess of get(i).subprocesses; let j=index">
                                        <tr class="subprocessRow">
                                            <td class="subprocessName">{{subprocess.name}}</td>
                                            <td class="subprocessState">
                                                <div 
                                                    style="pointer-events: auto; cursor: pointer;"
                                                    (click)="toggleLevelPopup($event)">
                                                        &nbsp;
                                                </div>
                                            </td>

                                            <td class="pop-up">
                                                <!-- <level-pop-up style="display: none;"></level-pop-up> -->
                                                <level-pop-up></level-pop-up>
                                            </td>

                                            <td class="descReq">

                                                <ng-container *ngIf="subprocess.descriptionReq.length>160">
                                                    <div 
                                                        style="cursor: pointer"
                                                        onclick="if(this.nextSibling.style.visibility==='hidden') this.nextSibling.style.visibility=''">
                                                            {{trim(subprocess.descriptionReq)}}
                                                    </div>                                                        
                                                    <text-pop-up style="visibility: hidden;" [popText]="subprocess.descriptionReq"></text-pop-up>
                                                </ng-container>

                                                <ng-container *ngIf="subprocess.descriptionReq.length<=160">
                                                    {{subprocess.descriptionReq}}
                                                </ng-container>

                                            </td>

                                            <td class="intentReq">

                                                <ng-container *ngIf="subprocess.intentReq.length>160">
                                                    <div 
                                                        style="pointer-events: auto; cursor: pointer"
                                                        onclick="if(this.nextSibling.style.visibility==='hidden') this.nextSibling.style.visibility=''">
                                                            {{trim(subprocess.intentReq)}}
                                                    </div>                                                        
                                                    <text-pop-up style="visibility: hidden;" [popText]="subprocess.intentReq"></text-pop-up>
                                                </ng-container>

                                                <ng-container *ngIf="subprocess.intentReq.length<=160">
                                                    {{subprocess.intentReq}}
                                                </ng-container>

                                            </td>
                                        </tr>
                                    </ng-container>      
                                </ng-container>
                            </table>
                        </td>
                    </tr>
                </ng-container>
                <ng-container *ngIf="i!==toggledIndex">
                    <tr style="display: none; height: 0; width: 100%">
                        <td colspan="4" style="height: fit-content; padding: 0 20px 0 20px;">
                            <table class="subprocessesTable">
                                <ng-container *ngIf="get(i)">
                                    <ng-container *ngFor="let subprocess of get(i).subprocesses; let j=index">
                                        <tr class="subprocessRow">
                                            <td class="subprocessName">{{subprocess.name}}</td>
                                            <td class="subprocessState">
                                                <div 
                                                    style="cursor: pointer;"
                                                    (click)="toggleLevelPopup($event)">
                                                        &nbsp;
                                                </div>
                                            </td>

                                            <td class="pop-up">
                                                <!-- <level-pop-up style="display: none;"></level-pop-up> -->
                                                <level-pop-up></level-pop-up>                                                
                                            </td>

                                            <td class="descReq">
                                                <ng-container *ngIf="subprocess.descriptionReq.length>160">
                                                    <div 
                                                        style="cursor: pointer"
                                                        onclick="if(this.nextSibling.style.visibility==='hidden') this.nextSibling.style.visibility=''">
                                                            {{trim(subprocess.descriptionReq)}}
                                                    </div>                                                        
                                                    <text-pop-up style="visibility: hidden;" [popText]="subprocess.descriptionReq"></text-pop-up>
                                                </ng-container>
                                                <ng-container *ngIf="subprocess.descriptionReq.length<=160">
                                                    {{subprocess.descriptionReq}}
                                                </ng-container>
                                            </td>

                                            <td class="intentReq">

                                                <ng-container *ngIf="subprocess.intentReq.length>160">
                                                    <div 
                                                        style="cursor: pointer"
                                                        onclick="if(this.nextSibling.style.visibility==='hidden') this.nextSibling.style.visibility=''">
                                                            {{trim(subprocess.intentReq)}}
                                                    </div>                                                        
                                                    <text-pop-up style="visibility: hidden;" [popText]="subprocess.intentReq"></text-pop-up>
                                                </ng-container>

                                                <ng-container *ngIf="subprocess.intentReq.length<=160">
                                                    {{subprocess.intentReq}}
                                                </ng-container>

                                            </td>
                                        </tr>
                                    </ng-container>      
                                </ng-container>
                            </table>
                        </td>
                    </tr>
                </ng-container>
            </ng-container>
        </table>
    </ng-container>
</div>

进程-menu.component.ts:

  httpSubscription1: any;
  httpSubscription2: any;
  httpSubscription3: any;
  processes: any = [];
  subprocessesOfProcess: any = [];
  toggledIndex: any;
  processesLoaded: Promise<boolean>;

  constructor(
    private globalData: DataBetweenUnrelatedService, 
    private httpService: HttpRetrieveService, 
    private router: Router, 
    private activatedRoute: ActivatedRoute){}

  ngOnInit(){
    this.activatedRoute.queryParams.subscribe (params => this.toggledIndex = parseInt(params["toggledIndex"]));

    console.log('INIT MENU', this.toggledIndex);

    this.httpSubscription1 = this.httpService.getData(myGlobals.URL+'/processes/allProcesses').subscribe(data => {
      this.processes = data;
      this.globalData.processExpansionState = [];
      this.globalData.subprocessesCalled = [];
      this.subprocessesOfProcess = [];
      for(let i=0; i<this.processes.length; i++){
        this.globalData.processExpansionState.push(i===this.toggledIndex ? true : false);
        this.globalData.subprocessesCalled.push(i===this.toggledIndex ? true : false);
        this.subprocessesOfProcess.push({});
      }
      this.processesLoaded = Promise.resolve(true);
    });
    
    this.httpSubscription2 = this.httpService.getData(myGlobals.URL+`/subprocesses/allSubprocessesOfAProcess?processId=${this.toggledIndex+1}`).subscribe( data => {
        this.subprocessesOfProcess[this.toggledIndex] = {
          processIndex: this.toggledIndex,
          subprocesses: data
        };
        this.save(this.toggledIndex, JSON.stringify(this.subprocessesOfProcess[this.toggledIndex]));
      });

  }

  ngOnDestroy(){
    if(this.httpSubscription1) this.httpSubscription1.unsubscribe();
    if(this.httpSubscription2) this.httpSubscription2.unsubscribe();
    if(this.httpSubscription3) this.httpSubscription3.unsubscribe();
    console.log('DESTROY MENU');
  }

  save(key, value){
    sessionStorage.setItem(key, value);
  }

  get(key){
    return JSON.parse(sessionStorage.getItem(key));
  }

  switchToOverview(event){
    this.router.navigate(['/','dashboard']);
  }

  trim(string){
    return string.slice(0, 160)+'...';
  }

  toggleLevelPopup(event){
    console.log(event.target.parentElement.parentElement.firstChild);
    // HERE IS WHERE I NEED TO SHOW OR HIDE MY CUSTOM POP-UP COMPONENT WHEN I CLICK 
    // ON THE ROW CHECKBOX
    // BUT THE PROBLEM IS THAT I CAN'T MAKE USE OF THE DYMANICALLY ADDED HTML, WHICH
    // ALSO IMPACTS THE POINTER EVENTS THAT I HAD MADE WITHIN THE POP-UP COMPONENT
    // (RENDERS IT USELESS BASICALLY)
  }

  toggleExpanded(event, i){
    let clickedRow: any;
    let expandedRow: any;
    let icon: any;
    let description1: any;
    let description2: any;
    
    if(i===this.toggledIndex){
      clickedRow = event.target.parentElement;
      expandedRow = event.target.parentElement.nextSibling;
      this.globalData.subprocessesCalled[i]=true;
    }else{
      clickedRow = event.target.parentElement;
      expandedRow = event.target.parentElement.nextSibling.nextSibling;
    }

    this.globalData.processExpansionState[i] = !this.globalData.processExpansionState[i];

    switch(this.globalData.processExpansionState[i]){
      case true:
        if(!this.globalData.subprocessesCalled[i]){
          this.httpSubscription3 = this.httpService.getData(myGlobals.URL+`/subprocesses/allSubprocessesOfAProcess?processId=${i+1}`).subscribe( data => {
            this.subprocessesOfProcess[i] = {
              processIndex: i,
              subprocesses: data
            };

            this.globalData.subprocessesCalled[i] = !this.globalData.subprocessesCalled[i];

            this.save(i, JSON.stringify(this.subprocessesOfProcess[i]));
          });
        }
        
        icon = clickedRow.children[0].children[0];
        icon.classList.remove('fa-chevron-right');
        icon.classList.add('fa-chevron-down');

        description1 = clickedRow.children[2];
        description2 = clickedRow.children[3];

        description1.classList.add('black');
        description1.classList.remove('white');
        description2.classList.add('black');
        description2.classList.remove('white');

        expandedRow.style.display = '';
        expandedRow.style.height = 'fit-content';

        break;

      case false:
        icon = clickedRow.children[0].children[0];
        icon.classList.remove('fa-chevron-down');
        icon.classList.add('fa-chevron-right');

        description1 = clickedRow.children[2];
        description2 = clickedRow.children[3];

        description1.classList.add('white');
        description1.classList.remove('black');
        description2.classList.add('white');
        description2.classList.remove('black');
        
        expandedRow.style.display = 'none';
        expandedRow.style.height = '0';
        break;
    }
  }
JavaScript HTML Angular HTTP 异步

评论


答: 暂无答案