简体   繁体   中英

How to make a dynamic form in angular with an ngfor?

I'm making a skills matrix which reads questions from the database and outputs them, then it asks the user for a number using radio buttons. I want to be able to send this data to the database in the format of (CurrentDate,score,skillID,UserID.

I tried to make a model of answer for each of the questions that were read in so each iteration of the for loop would have its own model of answer with the required data in so i could push all these to an array and then post this. Couldnt get it working but i think thats how it should be done.

TS:

 export class QuestionListComponent implements OnInit, OnDestroy{
        questions: Question[] = [];
        private questionsSub: Subscription;
        skillLevel = []
        energyLevel = []
        answerModels = []
        thisIsMyForm: FormGroup


        answerModel = new Answer(null,1,1,1);   

        @Input() Capability: string;
        constructor(public questionsService: QuestionService, private formBuilder: FormBuilder){
            let myDate = new Date();
            this.answerModel = new Answer(myDate,1,1,1);

            this.thisIsMyForm = new FormGroup({
                formArrayName: this.formBuilder.array([])
            })
            this.buildForm()
        }

        buildForm(){
            const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;

            Object.keys(this.questions).forEach((i) => {
                controlArray.push(
                    this.formBuilder.group({
                        SkillID: new FormControl({value: this.questions[i].SkillID, disabled: true}),
                        score: new FormControl({value: this.questions[i].score, disabled: true}),
                        date: new FormControl({value: this.questions[i].date, disabled: true}),
                    })
                )
            })
            console.log(controlArray)
        }


        ngOnInit(){
            this.questionsService.getQuestions().subscribe(
                data => {
                this.questions = [];
                Object.keys(data).map((key)=>{ this.questions.push(data[key])});
                console.log(this.questions);
                });


        }

        ngOnDestroy() {
            this.questionsSub.unsubscribe();
        }

    }

HTML:

<form id="myForm" [formGroup]="thisIsMyForm">
<div [formArrayName]="'formArrayName'">
<ul *ngFor="let question of questions[0]; let i = index">
    <div [formGroupName]="i">
    <form #userForm = "ngForm">

        <div *ngIf="question.Capability === Capability">
            <h3 class="SubCat">{{question.SubCategory}} {{question.Skill}}</h3>
                <div class="EandS">
                    <h4 class="skill">Skill</h4>
                    <h4 class="energy">Energy</h4>
                </div>

                <div class = "buttons">
                    <div class="skillButtons">
                        <mat-radio-group aria-label="Select your Skill Level" [(ngModel)]="skillLevel[i]" [name]="'completedSkills-' + i" >
                            <mat-radio-button  [value]="0" class="rbuttonSkill">0</mat-radio-button>
                            <mat-radio-button  [value]="1" class="rbuttonSkill">1</mat-radio-button>
                            <mat-radio-button  [value]="2" class="rbuttonSkill">2</mat-radio-button>
                            <mat-radio-button  [value]="3" class="rbuttonSkill">3</mat-radio-button>
                            <mat-radio-button  [value]="4" class="rbuttonSkill">4</mat-radio-button>
                        </mat-radio-group>
                    </div>

                    <div class="energyButtons">
                        <mat-radio-group aria-label="Select your Energy Level" [(ngModel)]="energyLevel[i]" [name]="'completedEnergy-' + i">
                                <mat-radio-button  [value]="1" class="rbuttonEnergy">1</mat-radio-button>
                                <mat-radio-button  [value]="2" class="rbuttonEnergy">2</mat-radio-button>
                                <mat-radio-button  [value]="3" class="rbuttonEnergy">3</mat-radio-button>
                        </mat-radio-group>

                    </div>
                </div>


                <div class="Selected answer">
                <strong>Seleted Answer : {{skillLevel[i]}} {{question.SkillID}} </strong>
                <strong>Seleted Answer : {{energyLevel[i]}} {{question.SkillID}}</strong>
                <strong>{{answerModel | json}}</strong>
                </div>


        </div>
    </form>
</div>
</ul>
</div>
</form>
<button  [disabled]="skillLevel[i]==undefined" mat-raised-button color="accent">save</button>

<pre>{{ skillLevel | json }}</pre>
<pre>{{ energyLevel | json }}</pre>

I think I need to get answer models for each question.

You are calling this.buildForm() in the constructor of your component - but you are not loading the questions until NgOnInit which is called after the component constructor - so when you build the form there are no questions to iterate.

You should call this.buildForm() in the subscription:

ngOnInit(){
        this.questionsService.getQuestions().subscribe(data => {
            this.questions = [];
            Object.keys(data).map((key)=>{ this.questions.push(data[key])});
            console.log(this.questions);

            this.buildForm();
        });
}

I'm also not sure that his line is correct in your html:

<ul *ngFor="let question of questions[0]; let i = index">

You should just be doing the following to iterate all the questions:

<ul *ngFor="let question of questions; let i = index">

EDIT I spent some time working a basic proof of concept out for you:

https://stackblitz.com/edit/angular-urgcdz

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM