我有一个用于计算嵌套数组的Angular 的简单指令:

import { AfterViewInit, Directive, Input, OnDestroy } from '@angular/core';

@Directive({
  selector: '[rhsNestedArrayCounter]',
  exportAs: 'rhsNestedArrayCounter'
})
export class NestedArrayCounterDirective implements AfterViewInit, OnDestroy  {
  static nextIndex = -1;

  @Input() appCounter: number | string = '';

  index;

  constructor() {
    this.index = NestedArrayCounterDirective.nextIndex++;
  }
  
  ngAfterViewInit(): void {
    if (typeof this.appCounter === 'string') {
      return;
    }
    NestedArrayCounterDirective.nextIndex = this.appCounter;
  }

  ngOnDestroy(): void {
    NestedArrayCounterDirective.nextIndex = -1;
  }
}

我在我的html中这样使用它,让我们称之为FormComponent:

<form [formGroup]="detailForm" class="form-container">
  <ng-container rhsNestedArrayCounter="0">
    <div *ngFor="let section of sections; let sectionIndex = index">
      <div class="section">
        <div class="section-content">
          <h3>{{ section.title }}</h3>
          <div formArrayName="responses">
            <div
              *ngFor="
                let questionWithAnswer of section.questionsWithAnswers;
                let questionIndex = index
              ">
              <div class="question">
                <div
                  rhsNestedArrayCounter
                  #counter="rhsNestedArrayCounter"
                  class="question-content"
                  [formGroupName]="counter.index">
                  <h4>
                    {{
                      questionWithAnswer.questionDescription
                        | textReplacer: '#EmployeeName':employeeName
                    }}
                  </h4>
                  <div>
                    <mat-form-field
                      color="accent"
                      id="sectionAnswer-{{ counter.index }}">
                      <textarea
                        matInput
                        placeholder="Answer"
                        formControlName="text"
                        name="text"
                        id="sectionAnswerInput-{{ counter.index }}"
                        [required]="questionWithAnswer.isRequired"
                        cdkTextareaAutosize
                        #autosize="cdkTextareaAutosize"
                        cdkAutosizeMinRows="2"
                        cdkAutosizeMaxRows="6"></textarea>
                      <mat-error
                        *ngIf="responses.controls[counter.index].get('text')?.errors?.['required']"
                        id="sectionAnswerError"
                        >Required field</mat-error
                      >
                      <mat-error
                        *ngIf="responses.controls[counter.index].get('text')?.errors?.['minlength']"
                        id="sectionAnswerMinLengthError"
                        >Min 2 characters</mat-error
                      >
                      <mat-error
                        *ngIf="responses.controls[counter.index].get('text')?.errors?.['maxlength']"
                        id="sectionAnswerMaxLengthError"
                        >Max 6000 characters</mat-error
                      >
                      <mat-error
                        *ngIf="responses.controls[counter.index].get('text')?.errors?.['pattern']"
                        id="sectionAnswerSpecialCharactersPatternError"
                        >Only letters, numbers, and some punctuation marks are
                        allowed.</mat-error
                      >
                    </mat-form-field>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </ng-container>
</form>

当我有一次在我的PageComponent中使用FormComponent时,一切都运行得很好,现在我有了一个PageTwoComponent,我需要多次使用FormComponent,因为这个计数器是全局的,所以我得到了关于索引的错误.例如,表单有15个问题,我得到了索引16的错误,因为当开始计算第二个FormComponent时,它从16开始,因为第一个FormComponent在15中完成(使用父组件中FormComponent的两倍).

enter image description here

所以我想也许可以在指令中使用字典,其中我 for each 组件都有一个唯一的索引,每个名称都有一个唯一的索引,但我不知道如何实现这一点,或者可能是另一个 idea (我是一名C#开发人员),欢迎任何帮助.

推荐答案

如果我理解正确的话,您希望这样使用rhsNestedArrayCounter="0"将计数器恢复到索引0,然后只使用rhsNestedArrayCounter来保存当前索引并递增它.

如果是这样的话,您应该首先使用ngOnInit挂钩,而不是ngAfterViewInit,并且,考虑到您的用法,在这里0将被作为字符串"0"传递.

let counterValue = -1; // would work almost the same as the static prop
class NestedArrayCounterDirective  {
  @Input() rhsNestedArrayCounter: number | string = ''; // name of the input matters.
  index: number;
  ngOnInit() {
    if(this.rhs) {
     counterValue = +this.rhs;
    } else {
      this.index = counterValue++;
    }
  }
  ngOnDestroy() { counterValue = -1;}
}

此外,为了避免在指令中初始化和清除"count",您可以为该计数器使用一个简单的服务,您只需将其放入父组件的providers部分

@Injectable()
class CounterService {
  private val = 0;  
  public getAndIncrement() {return this.val++;}
}

该服务基本上应该为FormComponent创建"作用域"版本的计数器,它应该为您解决这个问题

提供像这里这样的服务

@Component({providers: [CounterService],...}) cass FormComponent {}

并在指令中使用增量,如下所示

class NestedArrayCounterDirective {
  index = inject(CounerService).getAndIncrement();
}

即使没有任何挂钩,它也应该正常工作

Html相关问答推荐

简化指标与Delta保持一致

NG8004:找不到名为""的管道.'' [插件Angular 编译器]

你能让Cypress测试为p—fileUpload做文件上传吗?

当使用浮动标签和大小时,如何在 Select 组件中有更多可见选项?

摆动的html标签

OnChange函数未在下拉列表中使用一个选项触发

如何在R rmarkdown中创建循环中的分页表?

如何使用css横向显示英文和中日韩文字?

Django HTML标记-Merge for Loop with Conditional语句

如果您将带有 html 标签的字符串数据(name : test) 放在 `

使用shinyjqui拖放到网格表中

使用 Thymeleaf 将图像水平居中

Angular中如何向单选按钮添加验证

在 SQL 中合并 HTML 表中的单元格

发光效果html动画

如何创建带有偏移边框线的双色边框?

如何突出显示 .qmd html 文件中的特定代码行

在部分而不是正文中定义页面宽度

Bootstrap 5 网格问题,div 向下转义

下拉菜单项在页面加载时显示,需要隐藏直到悬停