Utilizing Angular 2's ngModel feature for dynamic objects and properties

Within my TypeScript file, I am dynamically generating properties on the object named selectedValsObj in the following manner:

private selectValsObj: any = {};

setSelectedValsObj(sectionsArr) {
  sectionsArr.forEach(section => {
    section.questions.forEach(questionObj => {
      if (questionObj.type === 'drop-down') {
        this.selectValsObj[questionObj.questionId] = { selected: questionObj.answerDetails[0] };
      }
    })
  });
}

When it comes to the HTML part, I desire to bind the [ngModel] attribute of my inputs to the properties existing within the selectValsObj object. Despite attempting various approaches, I have not been able to achieve the desired outcome:

<div *ngFor="let question of section.questions">
    <div class="drop-down-question" *ngIf="question?.type === 'drop-down'">
        <select class="q-select"
                [(ngModel)]="selectValsObj[questionId].selected" // <== doesn't work either**
                // [(ngModel)]="selectValsObj[{{ questionId }}].selected" // <== also doesn't work**
                name="answerForQuestion{{ question?.questionId }}">
            <option *ngFor="let answer of question?.answerDetails"
                [ngValue]="answer">
                    {{ answer?.value }}
            </option>
        </select>
    </div>
</div>

Is there a way for me to properly assign the ngModel within my HTML to a property that is created dynamically within my TypeScript file?

Answer №1

Upon attempting to replicate the scenario, I noticed multiple issues within the code snippet you provided.

  1. The property selectValsObj is declared as private, yet it is being utilized in the template.
  2. In the template, there is an attempt to iterate over section.questions, but this array is not defined elsewhere apart from the setSelectedValsObj method's local scope.
  3. You may be misusing your data due to a lack of type definitions.

This revised version includes inferred type definitions:

interface QuestionModel {
  type: string;
  questionId: string;
  answerDetails: string[];
}

const MOCK_DATA = [
  {
    questions: [{
      type: 'drop-down',
      questionId: '42',
      answerDetails: ['wololo'],
    }],
  },
];


@Component(...)
export class ProductsComponent {
  selectValsObj: { [key: string]: { selected: string } } = {};

  constructor() {
    this.setSelectedValsObj(MOCK_DATA);
  }

  setSelectedValsObj(sectionsArr: { questions: QuestionModel[] }[]) {
    sectionsArr.forEach(section => {
      section.questions.forEach(questionObj => {
        if (questionObj.type === 'drop-down') {
          this.selectValsObj[questionObj.questionId] = {selected: questionObj.answerDetails[0]};
        }
      });
    });
  }
}

Prior to implementation, ensure the type definitions align with your intentions to reduce potential errors.

Additionally, consider adopting a more declarative approach by utilizing map and filter for data manipulation instead of relying solely on forEach.

Answer №2

Review the HTML code snippet below:

[(ngModel)]="selectValsObj[questionId].selected"

If you have not defined a variable named questionId with a value in your TypeScript file, this could be causing an issue.

To obtain the questionId for each question within your section.questions loop, consider using the following modification:

[(ngModel)]="selectValsObj[question.questionId].selected"

I've included a simple example demonstrating various scenarios in this link (located in the src/app.ts). Hopefully, it provides some assistance.

Answer №3

(click)="toggle(personnel.id)"
  *ngIf="isToggled[personnel.id]"

in typescript file:

isToggled: any = {};

inside toggle method,

this.isToggled[personnelId] = !this.isToggled[personnelId];

Answer №4

  • Your intentions seem a bit unclear at the moment.
  • It appears that you are aiming to dynamically construct a page featuring questions and answers in a drop-down format, along with capturing the selected answer.
  • If this is the case, the code snippet below may be of assistance.

If so, the following Angular code can guide you:

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

interface Question {
  questionStr: string;
  questionId: string;
  type: string;
  answers: Array<string>;
  selectedAnswer: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'app';

  selectValsArr: Array<Question> = [];

  ngOnInit() {
    this.setSelectedValsObj([
      {
         questionStr : 'Question1',
         questionId: 'Q01',
         type: 'drop-down',
         answers: ['Q1Ans1', 'Q1Ans2', 'Q1Ans3'],
         selectedAnswer: null
      },
      {
        questionStr: 'Question2',
        questionId: 'Q02',
        type: 'drop-down',
        answers: ['Q2Ans1', 'Q2Ans2', 'Q2Ans3'],
        selectedAnswer: null
      },
    ]);
  }


  setSelectedValsObj(sectionsArr: Array<Question>) {
    sectionsArr.forEach(section => {
      if (section.type === 'drop-down') {
        this.selectValsArr.push(section);
        }
    });
  }
}

and HTML

<div *ngFor="let question of selectValsArr">
  <h3>{{question.questionStr}}</h3>
  <div class="drop-down-question">
    <select [(ngModel)]="question.selectedAnswer">
      <option value="">Select an Answer</option>
      <option *ngFor="let ans of question.answers" [ngValue]="ans"> {{ans}}</option>
    </select>
  </div>
</div>

<br>
<h2>Selected Answer</h2>

<div *ngFor="let question of selectValsArr">
    <span>{{question.questionStr}}</span>
    <span>&nbsp; &nbsp; - &nbsp; {{question.selectedAnswer}}</span>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to enhance focus on childNodes using Javascript

I am currently working on implementing a navigation system using a UL HTML Element. Here's the code I have so far: let htmlUL = <HTMLElement>document.getElementById('autocomplete_ul_' + this.name); if (arg.keyCode == 40) { // down a ...

What is the process for configuring React on one server and springboot on a separate server?

Can you help me with the setup of the following: Web Server : I need to set up a react + typescript application using npm at Backend Server : I also need to configure a Springboot backend server at I am currently using webpack to build the react applica ...

Typescript: Utilizing a generic array with varying arguments

Imagine a scenario where a function is called in the following manner: func([ {object: object1, key: someKeyOfObject1}, {object: object2, key: someKeyOfObject2} ]) This function works with an array. The requirement is to ensure that the key field co ...

Unable to input text in an Angular2 input field

Encountering an issue with users on Windows 7 using IE11 while trying to input information into textboxes or textareas. The drop-downs and checkboxes are functioning properly, but additional fields cannot be filled out even after toggling visibility with t ...

Comparing plain objects and class instances for modeling data objects

What is the recommended approach for creating model objects in Angular using TypeScript? Is it advisable to use type annotation with object notation (where objects are plain instances of Object)? For example, let m: MyModel = { name: 'foo' } ...

Testing Angular application with a currency pipe results in an error stating "currency

Utilizing the built-in angular currency pipe in my components works perfectly fine. However, when attempting to unit test my component, an error occurs: https://i.stack.imgur.com/J18JL.png I am using Angular 10 with Ivy and have imported the CommonModule, ...

Angular HTTP Interceptor encountering issue with TypeError: (0 , x.fromPromise) function is not recognized

I have implemented the following code snippet to attach reCAPTCHA v3 to an HTTP Request: @Injectable() export class RecaptchaInterceptor implements HttpInterceptor { constructor(private recaptchaService: ReCaptchaService) { } intercept(httpRequest: HttpRe ...

Utilizing TypeScript to define the parameter of a method within a generic interface by extracting a value from the generic type

In search of defining a versatile interface that can manage any Data type, I came up with an idea. This interface includes a dataKey property which simply holds a value of keyof Data. Additionally, it features a handler function where the parameter type sh ...

Tips for bringing in an enum from TypeScript?

I am working with a module defined in TypeScript that looks like this: declare module MyTypes { export enum MyEnum { GOOD = 'Good', BAD = 'Bad', UNKNOWN = '-' } export interface MyType1 { ...

Encountering a Start-up Issue with Angular2 on Windows 7

Just starting out with Angular and eager to dive deeper into Angular2. I meticulously followed the initiation guide to create the angular2-quickstart project. However, when executing the npm start command, the browser starts up but abruptly fails after jus ...

Create various Angular applications using PowerShell for efficient development

Currently, I am in the process of developing a PowerShell script that sequentially builds three different Angular applications. However, I am running into an issue where only the first app is built and the script stops without any errors or reaching the li ...

Guide to setting up a Cordova and TypeScript project using the command line interface

For my mobile application development, I rely on Cordova and execute cordova create MyApp in the command-line to initiate a new project. I am familiar with JavaScript but now require TypeScript for my project. Please assist me in setting up a Cordova pro ...

What is the best way to send ServerSideProps to a different page in Next.js using TypeScript?

import type { NextPage } from 'next' import Head from 'next/head' import Feed from './components/Feed'; import News from './components/News'; import Link from 'next/link'; import axios from 'axios&apo ...

Implementing a SetTimeout Function in HTML

Is there a way to delay calling the mouseHoverTableRow() function until after hovering on tr for 3 seconds? I only want to call this function if the hover duration is at least 3 seconds, as it triggers an API request. How can I achieve this? <tr *ngF ...

I am encountering unexpected behavior with NextJS's getInitialProps function, as it is giving me a compiler error stating "varName not found on type {}"

I seem to be stuck on a simple syntax issue while working with NextJs. I am attempting to perform dynamic server-side fetches using the getInitialProps pattern. However, the compiler is unable to recognize the return of getInitialProps in the regular func ...

The installation of Angular CLI through npm has unfortunately encountered an error

After following the steps from this post to remove the old installation, I encountered an issue during the last step: [sudo] npm uninstall -g @angular/cli [sudo] npm cache verify [sudo] npm install -g @angular/cli During the final step, I faced difficult ...

Guide to capturing the response in Angular 4 using HttpInterceptor

I have an Interceptor called TokenInterceptor: @Injectable() export class TokenInterceptor implements HttpInterceptor { constructor(private tokenService: TokenService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<Http ...

Warning in Typescript: potential undefined access detected when strict mode is enabled

When using Typescript with "strict": true in the tsconfig.json, a common issue arises where warnings are not triggered for potentially undefined properties, as shown by this code snippet: let x: any = { test: false } let y = x.asdf // no warning issued ...

Exploring the best practices for integrating Bootstrap into a Webpack and Angular2 project

I am looking to incorporate Bootstrap into my Angular2 project, including both the CSS and JS files. What is the best way to include these files in the project to ensure webpack functions properly? In the previous version using systemjs, it was included i ...

Using Angular 2 to convert and display data as a particular object type in

I have recently developed a basic application using the Angular2 tutorial as my guide. Initially, I established a straightforward "Book" model: /** * Definition of book model */ export class Book { public data; /** * Constructor for Book ...