Browse Source

自訂表單元件

修改部分fn Task改為any,規避TypeScript強型別問題,會導致編譯錯誤
修改task.ts 參數增加驚嘆號,不然需要設定初值
master
HarveyChou 2 years ago
parent
commit
ee4fc57944
  1. 18
      src/app/app.component.html
  2. 44
      src/app/app.component.ts
  3. 3
      src/app/app.module.ts
  4. 0
      src/app/task-form/task-form.component.css
  5. 4
      src/app/task-form/task-form.component.html
  6. 71
      src/app/task-form/task-form.component.ts
  7. 4
      src/app/task.ts

18
src/app/app.component.html

@ -1,15 +1,3 @@
<div [formGroup]="form">
<div>工作編號:{{ taskSn.value }}</div>
<div>
工作狀態:
<select formControlName="Status">
<option value="None">待安排</option>
<option value="Doing">進行中</option>
<option value="Finish">已完成</option>
</select>
</div>
<div>
完成日期:<input type="text" formControlName="FinishDate" />
<span *ngIf="finishDate.hasError('required')">完成日期為必填欄位</span>
</div>
</div>
<app-task-form [formControl] = "formControl"></app-task-form>
<pre>{{formControl.value | json}}</pre>

44
src/app/app.component.ts

@ -1,45 +1,11 @@
import { Component, OnInit } from '@angular/core';
import {
FormBuilder,
FormControl,
FormGroup,
Validators,
} from '@angular/forms';
import { map } from 'rxjs';
import { Component, VERSION } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
form: FormGroup = this.fb.group({
TaskSn: this.fb.control('0001'),
Status: this.fb.control('Finish'),
FinishDate: this.fb.control(''),
})
constructor(private fb: FormBuilder){}
get taskSn():FormControl{
return this.form.get('TaskSn') as FormControl;
}
get status(): FormControl{
return this.form.get('Status') as FormControl;
}
get finishDate(): FormControl{
return this.form.get('FinishDate') as FormControl;
}
ngOnInit(): void {
this.status.valueChanges
.pipe(map((status) => status ==='Finish'))
.subscribe({
next:(isFinish) =>{
if(isFinish){
this.finishDate.addValidators(Validators.required);
}else{
this.finishDate.removeValidators(Validators.required);
}
this.finishDate.updateValueAndValidity();
},
})
}
export class AppComponent{
readonly formControl= new FormControl();
}

3
src/app/app.module.ts

@ -4,10 +4,11 @@ import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { TaskFormComponent } from './task-form/task-form.component';
@NgModule({
imports: [ BrowserModule, ReactiveFormsModule, HttpClientModule ],
declarations: [ AppComponent ],
declarations: [ AppComponent, TaskFormComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

0
src/app/task-form/task-form.component.css

4
src/app/task-form/task-form.component.html

@ -0,0 +1,4 @@
<ng-container [formGroup]="form">
<div>工作事項:<input type="text" formControlName="subject" /></div>
<div>工作事項:<input type="text" formControlName="content" /></div>
</ng-container>

71
src/app/task-form/task-form.component.ts

@ -0,0 +1,71 @@
import { Subject, takeUntil } from 'rxjs';
import { Component, forwardRef, OnDestroy, OnInit } from '@angular/core';
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, FormBuilder, ControlValueAccessor, Validators, ValidationErrors } from '@angular/forms';
@Component({
selector: 'app-task-form',
templateUrl: './task-form.component.html',
styleUrls: ['./task-form.component.css'],
providers:[
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(()=> TaskFormComponent),
multi:true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(()=> TaskFormComponent),
multi:true,
},
],
})
export class TaskFormComponent implements OnInit, ControlValueAccessor, Validators, OnDestroy {
readonly form= this.fb.group({
subject: this.fb.control(''),
content: this.fb.control(''),
});
constructor(private fb: FormBuilder) { }
private readonly stop$ = new Subject<void>();
ngOnDestroy(): void {
this.stop$.next();
this.stop$.complete();
}
writeValue(data:any): void {//這裡data:Task改成data:any,規避patchValue(data)不可為空值
if(data){
this.form.patchValue(data);
}
}
registerOnChange(fn: ()=> void): void {
this.onChange=fn;
}
registerOnTouched(fn: ()=> void): void {
this.onTouched= fn;
}
setDisabledState?(disabled: boolean){
if(disabled){
this.form.disable();
}else{
this.form.enable();
}
}
onChange!:(_:Task) =>void;
onTouched!:() =>void;
ngOnInit(): void {
this.form.valueChanges
.pipe(takeUntil(this.stop$))
.subscribe((value:any) =>this.onChange(value));//這裡被增加了value:any,規避onChange(value)的需求
}
validate():ValidationErrors|null{
if(this.form.valid){
return null;
}
return {invalid:true};
}
}

4
src/app/task.ts

@ -0,0 +1,4 @@
export class Task {
subject!: string;
content!: string;
}
Loading…
Cancel
Save