TypeScript - วิธีการใช้สัญญาณกับ Angular Reactive Forms
ฉันมีฟอร์มที่ขับเคลื่อนด้วยเทมเพลตใน Angular 17 และฉันสามารถใช้สัญญาณกับฟอร์มของฉันแบบนี้:
@Component({
selector: 'app-root',
template: `
<input [ngModel]='firstName()' (ngModelChange)="firstName.set($event)">
<input [ngModel]='lastName()' (ngModelChange)="lastName.set($event)">
`,
})
export class App {
firstName= signal('first name');
lastName= signal('last name');
}
มีไอเดียไหมว่าฉันจะใช้สัญญาณของ Angular กับฟอร์มเชิงปฏิกิริยาได้อย่างไร?
คำตอบ #1
API ของฟอร์มแบบ Reactive ยังไม่รองรับสัญญาณ แต่มีคำขอฟีเจอร์ที่ได้รับการโหวตมากมาย: https://github.com/angular/angular/issues/53485 ดังนั้นเราสามารถคาดหวังว่าจะได้รับการสนับสนุนในเวอร์ชันอนาคตของ Angular ในระหว่างนี้ คุณสามารถใช้ toSignal() กับ observable valueChanges ได้ดังนี้:
myForm = new FormGroup({
firstName: new FormControl(''),
});
firstName = toSignal(this.myForm.controls.firstName.valueChanges);
greetingText = computed(() => `Hello ${this.firstName()}!`);
ถ้าแบบฟอร์มของคุณมีค่าตั้งต้น คุณสามารถใช้ตัวเลือก initialValue ของ toSignal():
myForm = new FormGroup({
firstName: new FormControl('John Doe'),
});
firstName = toSignal(
this.myForm.controls.firstName.valueChanges,
{ initialValue: this.myForm.controls.firstName.value },
);
greetingText = computed(() => `Hello ${this.firstName()}!`);
โปรดทราบว่า
toSignal()ปัจจุบันอยู่ในรุ่นพรีวิวสำหรับนักพัฒนาและอาจมีการเปลี่ยนแปลงก่อนที่จะมีความเสถียร
คำตอบ #2
เมื่อทำงานกับเทมเพลตที่ขับเคลื่อนโดยคุณสามารถทำได้เลย
@Component({
selector: 'app-root',
template: `
<input [(ngModel)]='firstName'>
<input [(ngModel)]='lastName'>
`,
})
export class App {
firstName= signal('first name');
lastName= signal('last name');
}
เมื่อทำงานกับ reactive จะมีการตั้งค่าโค้ดมากขึ้น แต่ที่นี่มีตัวอย่างโค้ด บทเรียน และการสาธิตบน stackblitz ที่ถูก fork แสดงวิธีการใช้งาน
คุณไม่สามารถใช้สัญญาณกับการควบคุมแต่ละรายการได้ แต่คุณสามารถแปลงการเปลี่ยนแปลงของการควบคุมเป็นสัญญาณและใช้มันร่วมกับการรวมของ computed และ effect เพื่อให้ได้หลายสถานการณ์
ฟอร์มเชิงปฏิกิริยา Angular (17+) + สัญญาณ & คอมโพเนนต์แบบสแตนด์อโลน
...
export class ProfileEditorComponent {
profileForm!: FormGroup;
firstnameSignal: Signal<any> | undefined;
constructor(private fb: FormBuilder) {
this.profileForm = this.fb.group({
firstname: new FormControl('', Validators.required),
lastname: new FormControl('', Validators.required),
email: new FormControl('', Validators.required),
gender: new FormControl('', Validators.required),
country: new FormControl('', Validators.required),
});
// firstNameSignal is created using the toSignal function.
// represents the value of the 'firstName' form control.
// so now instead of manually subscribing to the valueChanges of the form control, we can directly use the signal in our template
this.firstnameSignal = toSignal(
this.profileForm.get('firstname')?.valueChanges.pipe(debounceTime(300)) ??
of(null),
{}
);
}
onSubmit() {
console.log('submited values: ', this.profileForm.value);
}
}
