1

我正在尝试更新从服务收集的嵌套数据。*ngFor我通过使用填充输入值以 html 表单显示数据库数据。

当我尝试提交这个时,它总是给我null,因为我还没有真正接触过这些领域。奇怪的是,当我为该字段输入新值或编辑给定值时,它确实通过了它们。在正常情况下,这正是我想要的。

但在这种情况下,如果我只编辑第一个字段和submit表单,它只会传递第一个字段的值并null为其他字段提供。

换句话说,用表单数据覆盖现有数据对我来说是危险的,因为除了第一个数据之外,它会用 null 覆盖所有数据。

- - - - - 编辑 - - - - -

下面的代码现在可以使用 FormBuilder。它通过循环主数组长度的循环生成这些字段(下图)。

用清晰的语言:数组包含可变数量的对象。每个对象都有:

  • 标题(第一个输入字段)
  • 标头大小(第二个输入)
  • 可变数量的段落

每个组都用一个<hr>标签封闭。

您还可以看到我填写了each输入字段的value标签,使用*ngFor(见下面的 html)。

现在的问题是,如果我submit在不更改任何值的情况下创建表单,我会得到一个包含所有正确键的对象数组,它们的所有值都设置为,null因为我实际上没有编辑这些字段。

如果我提交,我想检索一组对象及其值,即使我没有编辑一个对象。

否则我将不得不编写一个复杂的功能来仅覆盖 value 所在的当前数据is not null

所以我的实际问题是:

即使我没有编辑(触摸)单个字段,是否有办法检索所有值?还是我应该使用其他方法?

在此处输入图像描述

如果我submit得到这个表格(因为我实际上没有编辑过一些东西):

在此处输入图像描述

HTML:

<h3>Description</h3>
<form [formGroup]="colForm" (submit)="updateCol(colForm); $event.preventDefault()">
    <div class="margin-bottom-30" *ngFor="let col of overall_data.value.cols; let i=index">
        <div [formGroupName]="i">
            <div class="form-group" formGroupName="title">
                <input class="form-control" type="text" formControlName="text" name="text" value="{{ col.title.text }}">
                <input type="number" class="form-control" formControlName="size" name="size" min="1" max="5" value="{{ col.title.size }}">
            </div>
            <div formGroupName="body">
                <div formArrayName="paragraphs"> 
                    <div *ngFor="let p of col.body.paragraphs; let pi=index">
                        <div class="form-group" [formGroupName]="pi">
                            <textarea class="form-control" formControlName="text" cols="30" rows="10" value="{{ p.text }}"></textarea>
                            <div *ngIf="p.classes" formArrayName="classes">
                                <div *ngFor="let class of p.classes">
                                    <input type="text" name="class" class="form-control" value="{{ class }}">
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <hr>
    </div>
    <div class="form-group">
        <input type="submit" class="btn btn-custom" value="Save">
    </div>
</form>

打字稿文件:

export class AdminWebComponent implements OnInit {
    overall_data: any;
    id: string;
    errorMessage: string;
    colForm: FormArray = this._fb.array([]);

constructor(private _skillsService: SkillsService, private _fb: FormBuilder) {

    // work with form groups: https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2
}

ngOnInit(): void {
    this._skillsService.getByKey('web')
    .subscribe(
        overall_data => this.overall_data = overall_data,
        error => this.errorMessage = error,
        () => { 
            this.id = this.overall_data['id'];

            // cols
            for (var i = 0; i < this.overall_data.value.cols.length; ++i) {
                this.colForm.push(this.initCols()) // in for loop so we can have a dynamic amount of cols
            }

            // charts

        }
    );
}

// init functions
initCols(): any {
    return this._fb.group({ // need to be called twice because array has 2 items, makes this dynamic?
        title: this._fb.group({ 
            text: [""], 
            size: [0]
        }),
        body: this._fb.group({
            paragraphs: this._fb.array([
                this.initParagraphs(),
                this.initParagraphs()
                ])
        })
    })
}
initParagraphs(): any {
    return this._fb.group({
        text: [""],
        classes: this._fb.array([])
    })
}


// update functions
updateCol(colForm: any): void {
    console.log(this.id);
    console.log(colForm.value);

    // this._skillsSevice()
    // .
}

-------已解决--------

这并不简单(对我来说),但我必须做的事情真的很明显......我必须删除value binding我在 中所做的HTML,而是使用 for 循环用 formbuilder 填充值。

似乎尝试将表单生成器控件与 HTML 中生成的值结合起来并不是一个好主意,也不是很合乎逻辑。最好在 TypeScript 文件中而不是在 HTML 中处理我的复杂数据。

打字稿调整:

...
ngOnInit(): void {
    this._skillsService.getByKey('web')
    .subscribe(
        overall_data => this.overall_data = <ISkills>overall_data,
        error => this.errorMessage = error,
        () => { 
            this.id = this.overall_data['id'];

            // cols
            for (var i = 0; i < this.overall_data.value.cols.length; ++i) {
                this.colForm.push(this.initCols(this.overall_data.value.cols[i])) // in for loop so we can have a dynamic amount of cols
            }

            // charts

        }
    );
}

// init functions
initCols(cols: ICols): any {
    // console.log(cols);
    return this._fb.group({ // need to be called twice because array has 2 items, makes this dynamic?
        title: this._fb.group({ 
            text: [ cols.title.text ], 
            size: [ cols.title.size ]
        }),
        body: this._fb.group({
            paragraphs: this.initParagraphs(cols.body.paragraphs)
        })
    })
}
initParagraphs(paragraphs: IParagraph[]): any {
    let arr: FormArray = this._fb.array([]);

    for (var i = 0; i < paragraphs.length; ++i) {
        arr.push(
            this._fb.group({
                text: [ paragraphs[i].text ],
                classes: this._fb.array([ paragraphs[i].classes ])
            })
        )
    }
    return arr;
}
...
4

0 回答 0