iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0

昨天畫面雖然橋正常了
不過似乎還有些問題
我們來檢查一下
換頁的時候有點狀況
切換頁面的時候畫面有點異常
檢查一下form-input的程式

ngOnChanges(): void
{
    this.pageSetting.form = this.fb.group({});
    this.pageSetting.fieldSettings.forEach(setting =>
    {
        let newControl = this.fb.control(setting.defaultValue, { validators: setting.validator });
        if (!setting.groupName)
        {
            this.innerForm.addControl(setting.name, newControl);
        } else
        {
            if (!this.innerForm.contains(setting.groupName))
            {
                this.innerForm.addControl(setting.groupName, new FormGroup({}));
            }
            (this.innerForm.get(setting.groupName) as FormGroup).addControl(setting.groupType!, this.fb.control(setting.defaultValue, { validators: setting.validator }))
        }
        (this.pageSetting.form as FormGroup).addControl(setting.name, newControl);
    })
}

我們頁面在切換的時候會觸發這個onChange事件
所以切換的時候應該會重新產生innerForm進而更新畫面上欄位
不過這邊很明顯的 我們沒有清空innerForm
所以調整一下

ngOnChanges(): void
{
    this.pageSetting.form = this.fb.group({}); 
    this.innerForm = this.fb.group({}); //重設innerForm
    this.pageSetting.fieldSettings.forEach(setting =>
    {
        let newControl = this.fb.control(setting.defaultValue, { validators: setting.validator });
        if (!setting.groupName)
        {
            this.innerForm.addControl(setting.name, newControl);
        } else
        {
            if (!this.innerForm.contains(setting.groupName))
            {
                this.innerForm.addControl(setting.groupName, new FormGroup({}));
            }
            (this.innerForm.get(setting.groupName) as FormGroup).addControl(setting.groupType!, this.fb.control(setting.defaultValue, { validators: setting.validator }))
        }
        (this.pageSetting.form as FormGroup).addControl(setting.name, newControl);
    })
}

然後我們邊發現一個小小的問題
那就是元件內的檢核問題
會顯示檢核錯誤 但是還是可以下一頁
因為我們在產生form跟innerForm其實是兩個不同的formControl
這邊會改用一個比較不一樣的寫法
先新增到form
然後再把form的formControl新增到innerForm裡面

ngOnChanges(): void
    {
        this.pageSetting.form = this.fb.group({});
        this.innerForm = this.fb.group({});
        this.pageSetting.fieldSettings.forEach(setting =>
        {
            let newControl = this.fb.control(setting.defaultValue, { validators: setting.validator }) as FormControl;
            
            (this.pageSetting.form as FormGroup).addControl(setting.name, newControl);
            if (!setting.groupName)
            {
                this.innerForm.addControl(setting.name, newControl);
            } else
            {
                if (!this.innerForm.contains(setting.groupName))
                {
                    this.innerForm.addControl(setting.groupName, new FormGroup({}));
                }
                (this.innerForm.get(setting.groupName) as FormGroup).addControl(setting.name!, this.pageSetting.form?.get(setting.name))
            }
        })
    }

不過我們發現 這樣雖然formControl會跟著變 但是pegeSetting.form的檢核卻沒有刷新
看來雖然想偷懶 還是得寫valueChange
於是我們這邊再加上form裡面formControl的valueChange監聽
觸發後刷新form的檢核狀態

    (this.pageSetting.form?.get(setting.name) as FormGroup)
    .valueChanges.pipe(takeUntil(this.destroy$)).subscribe(v=>{
        this.pageSetting.form?.updateValueAndValidity();
    })

然後為了不要混淆狀態
這邊把form跟innerForm的欄位名稱改成一樣
昨天我們是用groupType當innerForm的欄位名稱
改回使用name
這樣有好幾個function要跟著調整

// form-input.compnent.ts
ngOnChanges(): void
{
    this.pageSetting.form = this.fb.group({});
    this.innerForm = this.fb.group({});
    this.pageSetting.fieldSettings.forEach(setting =>
    {
        let newControl = this.fb.control(setting.defaultValue, { validators: setting.validator }) as FormControl;

        (this.pageSetting.form as FormGroup).addControl(setting.name, newControl);
        if (!setting.groupName)
        {
            this.innerForm.addControl(setting.name, newControl);
        } else
        {
            if (!this.innerForm.contains(setting.groupName))
            {
                this.innerForm.addControl(setting.groupName, new FormGroup({}));
            }
            // 這邊addControl的第一個參數改成setting.name
            (this.innerForm.get(setting.groupName) as FormGroup).addControl(setting.name!, this.pageSetting.form?.get(setting.name))
        }

        (this.pageSetting.form?.get(setting.name) as FormGroup)
        .valueChanges.pipe(takeUntil(this.destroy$)).subscribe(v=>{
            this.pageSetting.form?.updateValueAndValidity();
        })
    })
}
    
...
// 篩選組合元件用的setting
getSettingsByForm(settings: FieldSetting[], fg: FormGroup): FieldSetting[]
{
    return Object.keys(fg.value).map(v =>
    {    
        // 這邊改成用name去取settings
        return settings.find(setting => setting.name === v) as FieldSetting;
    })
}
    
// combo-phone.component.ts
    getControl(group: FormGroup, groupType: string)
    {
        return (group?.get(this.getSettingByGroupType(groupType).name) as FormControl)|| new FormControl()
    }

combo-phone裡面 如果name每次都不一樣 那html的部分要再額外取name
這邊我們不調整html的部分
傳進來的groupType再用getSettingByGroupType取得的setting可以取得name

調整了不少
可能有點混亂
不過我們組合元件的大方向也訂出來了
接下來幾天再處理一些其他的組合元件

今日程式:day19


上一篇
第18天 組合元件-電話(中)
下一篇
第20天 重構組合元件 及 組合元件radio+text
系列文
簡單的事 最困難-Angular動態Form元件30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言