Angular binding object with array from component to view with ngModels

I tried to bind my model on my view, but I have a problem when I submit my form : I don't have an array, but many property.

component :

export class QuizFormAddQuestionComponent implements OnInit {
    public question: Question;

    constructor() {
        this.question = new Question();
    }

    ngOnInit() {
        this.question.setModel({ question: 'test' });
        this.question.setAnswers(3);
    }

    createQuestion(form) {
        console.log(form.value);
    }

}

my template :

<hello name="{{ name }}"></hello>

<div class="row">
    <div class="col-sm-1"></div>
    <div class="col-sm-10">

        <form #form="ngForm" (ngSubmit)="createQuestion(form)" class="mt-4">
            <div class="form-row">
                <div class="form-group col-md-12">
                    <label for="question" class="col-form-label">Question</label>
                    <input type="text"
                           class="form-control"
                           id="question"
                           placeholder="Enter your question..."
                           name="question"
                           [ngModel]="question.question"
                           required>
                </div>
            </div>
            <div class="form-group row" *ngFor="let answer of question.answers; let i = index;">
                <div class="col-sm-12">
                    <div class="form-check">
                        <label class="form-check-label">
                            <input class="form-check-input"
                                   type="checkbox"
                                   id="answer-value-{{i}}"
                                   [ngModel]="question.answers[i].value"
                                   name="answers[{{i}}].value">
                            Answer {{ i }}
                        </label>
                    </div>
                    <input type="text"
                           class="form-control"
                           id="answer-text-{{i}}"
                           [ngModel]=question.answers[i].text
                           name="answers[{{i}}].text">
                           {{ answer.getManipulateObjet() }}
                </div>
            </div>
            <div class="form-row">
                <div class="form-froup col-md-12 text-right">
                    <button type="submit" class="btn btn-primary">Add question</button>
                </div>
            </div>
        </form>
    </div>
</div>

question.ts (model)

import { Answer } from "./answer";

export class Question {

    constructor(private question: string          = '',
                private answers: any[]            = [],
                private more_informations: string = '',
                private difficulty: number        = 0,) {
    }

    setModel(obj) {
        Object.assign(this, obj);
    }

    addAnswer() {
        let new_answer = new Answer();

        new_answer.setModel({ text: 'test', value: false });

        this.answers.push(new_answer);
    }

    setAnswers(number_answers) {
        for (let i = 0; i < number_answers; i++) {
            this.addAnswer();
        }

        console.log(this);
    }

}

answer.ts (model)

export class Answer {

    constructor(private text: string  = '',
                private value: boolean = false,) {
    }

    setModel(obj) {
        Object.assign(this, obj);
    }

    getManipulateObjet() {
      return '=== call getManipulateObjet() for example : return more information after manipulating object, count value properties, concat, etc... ===';
    }

    getCount() {
      // ....
    }

    getInspectMyObject() {
      // ...
    }
}

initial object :

在这里输入图像描述

console after submit :

在这里输入图像描述

After the submit I would like the same things as the initial object (same structure with the data updated), the same data structure before and after submit

I tried this on in my view, but it doesn't work :

<div class="form-group row" *ngFor="let answer of question.answers; let i = index;">
    <div class="col-sm-12">
        <div class="form-check">
            <label class="form-check-label">
                <input class="form-check-input"
                       type="checkbox"
                       id="answer-value-{{i}}"
                       [ngModel]="answer.value"
                       name="answer[{{i}}].value">
                Answer {{ i }}
            </label>
        </div>
        <input type="text"
               class="form-control"
               id="answer-text-{{i}}"
               [ngModel]=answer.text
               name="answer[{{i}}].text">
               {{ answer.getManipulateObjet() }}
    </div>
</div>

I transform in the *ngFor [ngModel]=question.answers[i].text by [ngModel]="answer.text" , but I have the same problem...

I tried many things from differents posts : Angular 2 form with array of object inputs, Angular 2 - 2 Way Binding with NgModel in NgFor

But always many properties and no array

I would like to do this without reactive form, only template driven

Demo:

https://angular-by7uv1.stackblitz.io/

I would like to use different function from my object 'answer', for example : answer.getInformation(), getCount(), getInspectMyObject() etc.. to iterate on my object only, in my view. This function is provided by my model 'Answer' to have a clean code in my view. I would like use many functions from my model in the *ngFor. If I use the reactive form, I can't use different function from my model because the "link" between my parent object and my childs is broken.

SOLVED

https://fom-by-template-driven.stackblitz.io


The problem is, whatever the input name specified, it will be considered as just text. Should not reference any Object or Array .But with slight modifications, there is a chance to obtain the same data structure with updated data.

All elements are binded in one way, so make it two way binding. So whenever input value changes, The binded element value updates.

 [(ngModel)]="question.question"

Use template driven form for validation

<form #form="ngForm" (ngSubmit)="createQuestion()" class="mt-4">
...
<button [disabled]="!form.valid"  

Now the values are validated & updated in the variable question .There is no need to get the value from form, use the updated object question to create question.

createQuestion() {
        console.log(this.question);
    }

View the results in worked out App


你可以做这样的事情: -

import {Component, OnInit} from '@angular/core';

import {FormGroup, FormArray, FormControl} from '@angular/forms';

@Component({

  selector: 'form-component',

  template: `

    <form [formGroup]="formGroup">
      <div formArrayName="inputs" *ngFor="let control of formArray;     let i = index;">
        <input placheholder="Name please" formControlName="{{i}}"/>
      </div>
    </form>

    <button (click)="addInput()">Add input</button>

  `
})

export class FormComponent implements OnInit{

  formGroup: FormGroup;


  contructor() {
  }


  ngOnInit(){

    this.formGroup = new FormGroup({
      inputs: new FormArray([
        new FormControl("Hello"),
        new FormControl("World"),
      ]);
    });
  }

  get formArray() {

    return this.formGroup.get('inputs').controls
  }


  addInput(){

    this.formArray.push(new FormControl("New Input"));
  }

}

i see that you are using [ngModel] in you html template. this will only bind the input to bind the output as well you need to use [(ngModel)] . this is the regular way of using ngModel . i find one more wrong in your code that name="answer[{{i}}].value" here name is value should be constant, you are giving it as variable the correct way of writing it is name="{{answer[i].value}}"

在这里输入图像描述

链接地址: http://www.djcxy.com/p/40466.html

上一篇: 直观的理解功能,参考参考文献

下一篇: 带有ngModels查看组件的角度绑定对象