使用新的 input() 信号进行指令输入

问题描述 投票:0回答:1

我已成功将 Angular 18 项目迁移到 Angular 19,并用新的 input() 信号替换了所有 @Input 装饰器。代码可以工作,但对带有 input() 信号的指令的测试会中断。

这是我的指令,它只是将表单组的值相乘。

import { Directive, OnInit, input } from "@angular/core";
import { FormGroup, FormGroupDirective } from "@angular/forms";
import { FormItem } from "../model/form.model";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";

@UntilDestroy()
@Directive({
  selector: "[appMultiply]",
  standalone: true,
})
export class MultiplyDirective implements OnInit {
  constructor(formGroupDirective: FormGroupDirective) {
    this.form = formGroupDirective.form;
  }

  readonly appMultiply = input<FormItem>();
  readonly formDefinition = input<Array<FormItem>>();

  private form: FormGroup;

  ngOnInit(): void {
    const appMultiply = this.appMultiply();
    if (!appMultiply?.multiply || !this.formDefinition()) {
      return;
    }

    const sourceControl = this.form.get(appMultiply.formControlName);

    if (!sourceControl) {
      return;
    }

    //initial calculation
    this.calculateTargetControlValues(appMultiply, sourceControl.value);

    //wait for source changes
    sourceControl.valueChanges
      .pipe(untilDestroyed(this))
      .subscribe((value) =>
        this.calculateTargetControlValues(this.appMultiply()!, value),
      );
  }

  private calculateTargetControlValues = (
    appMultiply: FormItem,
    sourceValue: number,
  ) => {
    const multiplyByControl = this.form.get(
      appMultiply.multiply!.multiplyByControlName,
    );

    if (!multiplyByControl) {
      return;
    }

    this.formDefinition()!
      .filter((formItem) =>
        this.appMultiply()!.multiply!.targetFormControlNames.includes(
          formItem.formControlName,
        ),
      )
      .forEach((formItem) => {
        const targetControl = this.form.get(formItem.formControlName);
        if (!targetControl) {
          return;
        }
        const result = (sourceValue ?? 0) * (multiplyByControl.value ?? 0);
        targetControl.patchValue(result, { emitEvent: false });
      });
  };
}

这是该指令的基本测试:

import { FormGroupDirective } from "@angular/forms";
import { MultiplyDirective } from "./multiply.directive";

describe("MultiplyDirective", () => {
  it("should create an instance", () => {
    const directive = new MultiplyDirective(new FormGroupDirective([], []));
    expect(directive).toBeTruthy();
  });
});

我从 Karma 收到此错误:“错误:NG0203:inputFunction() 只能在注入上下文中使用,例如构造函数、工厂函数、字段初始值设定项或与

runInInjectionContext
一起使用的函数。了解更多信息https://angular.dev/errors/NG0203”

如果我用 @Input 装饰器输入替换 2 个输入信号,测试将成功运行。像这样:

  @Input() appMultiply!: FormItem
  @Input() formDefinition!: Array<FormItem>

我做错了什么?

angular typescript testing karma-jasmine upgrade
1个回答
0
投票

新信号

input()
要求您使用依赖项注入上下文创建组件。

要使用

TestBed
测试指令,您需要通过主机组件来完成。

@Directive({selector: '[appMultiply]'})
class MultiplyDirective {
  ...
}

@Component({
  imports: [ReactiveFormsModule, MyDirective],
  template: `<form [formGroup]="fg" myDir></form>`
})
class TestComponent {
  fg= new FormGroup({foo: new FormControl('bar')})
}

const fixture = TestBed.createComponent(TestComponent);
const directive = fixture.debugElement.query(By.directive(MyDirective));

console.log(directive);
expect(directive).toBeDefined();
expect(directive.componentInstance.formGroupDirective).toBeDefined()
© www.soinside.com 2019 - 2024. All rights reserved.