Issue with displaying selected value and options in Mat-select when using formarray - Reactive forms in Angular

I've been working on the code below to create dropdowns, but I'm having trouble getting the selected value and options to show up in the dropdowns. Can you help me figure out what's wrong with the code?

Component code

testForm: FormGroup;
get ctrls() {
  return this.testForm.get('ctrls') as FormArray;
}
data = [{
    initial: 'hen',
    options: ['hen', 'duck', 'parrot']
  },
  {
    initial: 'lion',
    options: ['lion', 'tiger', 'cheetah']
  }
];

constructor(private router: Router, private formBuilder: FormBuilder) {
  this.testForm = this.formBuilder.group({
    ctrls: this.formBuilder.array([])
  });
  for (let i = 0; i < this.data.length; i++) {
    this.ctrls.push(this.formBuilder.control(this.data[i]));
  }
}

Template code

<form [formGroup]="testForm">
  <div formArrayName="ctrls" *ngFor="let animals of ctrls.controls; let i = index">
    <mat-form-field>
      <mat-select [formControlName]="i" [(value)]="animals.value.initial">
        <mat-select-trigger>{{ animals.value.initial }}</mat-select-trigger>
        <mat-option *ngFor="let animal of animals.value.options" [value]="animal">{{ animal }}</mat-option>
      </mat-select>
    </mat-form-field>
  </div>
</form>

I would appreciate any guidance on how to fix this issue...

Please click here to visit the stackblitz link and see the problem for yourself.

Answer №1

Instead of relying on the controller options, utilize the options from the data itself.

Make sure to initialize your formControl using this.data[i].initial, as the data is a string and not an object. I made some changes to the HTML by using the controller instead of controllerName since you already have access to it. Additionally, I removed the [value]-attribute in the mat-select because the value is being set in the component. Using [value] is more suitable for template-driven forms rather than reactive forms, and combining both may cause unintended consequences.

HTML:

<form [formGroup]="testForm">
  <div *ngFor="let animals of ctrls.controls; let i = index">
    <mat-form-field>
      <mat-select [formControl]="animals">
        <mat-option *ngFor="let animal of data[i].options" [value]="animal">{{ animal }}</mat-option>
      </mat-select>
    </mat-form-field>
  </div>
</form>

And in the TypeScript file:

ngOnInit() {
 this.testForm = this.formBuilder.group( {
   ctrls : this.formBuilder.array( [] )
 });
 for( let i = 0; i < this.data.length; i++ ) {
   this.ctrls.push( this.formBuilder.control( this.data[ i ].initial ) );
 }
}

https://stackblitz.com/edit/angular-material-design-q3wbah

EDIT:

Based on the feedback about wanting an object as the data in the formControl, consider modifying the data structure as shown below.

  data = [ 
    { options : [
      {name:'hen', icon: 'someIcon'},
      {name:'duck', icon: 'asd'},
      {name: 'parrot', icon: 'asdasd'} ] }
  ];

If you need to set the correct initial object, match the name with your initial object to ensure you get the right reference. In the example below, I've only selected the first element.

You can then use the <mat-select-trigger> as initially intended.

https://stackblitz.com/edit/angular-material-design-new-data

Answer №2

There seems to be a typo in your code

animmal

In addition, it is recommended to move the code from the constructor to the ngOnInit method

Take a look at: https://stackblitz.com/edit/angular-material-design-m491ic?file=src%2Fapp%2Fapp.component.ts

Furthermore, it appears that there is confusion with the formControls. I have made some adjustments to the logic, hoping it will be helpful.

Essentially, the options should be outside of the formcontrol

<mat-form-field>
  <mat-select
  [formControl]="animals"
  >
    <mat-option 
      *ngFor="let animal of data[i].options; let j = index"
      value="{{animal}}"
    >{{ animal }}</mat-option>
  </mat-select>
</mat-form-field>

I also made changes to the formgroup definition

this.testForm = this.formBuilder.group( {
      ctrls : this.formBuilder.array( [] )
    } );
    for( let i = 0; i < this.data.length; i++ ) {
      this.ctrls.push( new FormControl({value: this.data[i].initial, disabled: false}) );
    }

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

Nesting / Mulled / JS - Uploading Files - Form's end is unexpectedly reached

I have successfully implemented the upload file functionality in my Nest.js server application, but I am facing an issue when trying to use it with JavaScript/React. @Post('upload') @UseInterceptors(FileInterceptor('file')) upl ...

Mapping Form Fields (with Formik)

Currently, the Formik/Yup validation setup in my form is working perfectly: export default function AddUserPage() { const [firstName, setFirstName] = useState(""); const [email, setEmail] = useState(""); return ( <div> <Formik ...

Transforming BufferGeometry to Geometry using FBXLoader within the Three.js library

Check out my snippet below for loading a .fbx object. It defaults to loading an object as BufferGeometry: const loader = new THREE.FBXLoader(); async function loadFiles(scene, props) { const { files, path, childName, fn } = props; if (index > fi ...

Is there a way to unshackle myself from the promise chain in Express and trigger an error ahead of time

Upon examining my request handler, it appears as follows: router.post('/', function(req,res) { var screencast; var channel; youtube.get(req.body.videoId).then(function(data) { screencast = data.screencast; channel = data.channel; ...

Services that are not configured as singleton instances

In my view, I am utilizing a file upload component multiple times. Each uploading file is managed by a service that handles its metadata. However, when I add files to one component, all the components begin updating instead of just the intended one. Is it ...

Return true for cucumber datatable in typescript without fail

I am facing an issue where the following step definition always returns true even for incorrect data from the dataTable. Can someone assist me in correcting the syntax in TypeScript with Chai assertions? Then(/^Verify the following details in report$/, a ...

Error: The property 'ss' cannot be accessed because it is undefined

Our main source page will be index.html, while Employees.html is where our results end up. An error occurred: TypeError - Cannot read property 'ss' of undefined Error in the code: let rating = req.body.ss; Seeking assistance please >< C ...

What is the best way to design a Global Navigation menu for websites?

For example, I am looking to integrate a Navigation menu into my website using just one file. I have considered using PHP or creating an HTML frame, but I am wondering what the current industry standard is for professionals. Any insights? ...

The functionality for transferring ERC20 claim tokens seems to be malfunctioning

I am facing an issue with my contract while trying to execute the claimFreeToken function. Even though the contract does not have enough tokens, the function does not return an error and the token also does not get received. Can anyone point out where I ...

Use two queries to apply filters to entries in NextJS

Greetings to all! I am currently working on a project in NextJS that involves showcasing a portfolio of works generated from JSON data. [ { "title": "WordPress Plugin for Yandex Recommender Widget", "image" ...

Multiple change events triggered in AJAX interactions

Having a list of doctors in a dropdown menu with an ID of "doctors", I use AJAX to fetch related locations based on the selected doctor. These retrieved locations are then displayed in another dropdown menu with an ID of "locations". Subsequently, chan ...

Enhancing ajax content with Rx.Observable.fromEvent: A step-by-step guide

I am currently fetching content using Ajax, in the form of a json object, which is then displayed in the browser. var stateSubjectSub = stateSubject.subscribe(function(data) { console.log('state changes'); console.log(data); var list = document ...

Tips on retrieving a value nested within 3 layers in Angular

In my Angular application, I have three components - A, B, and C. Component A serves as the main component, Component B is a smaller section nested inside A, and Component C represents a modal dialog. The template code for Component A looks something like ...

Issue with Displaying Local Server Image in Angular 2 HTML

I am facing an issue with my Angular 2 Application. It retrieves items from a local database where the server stores the image of the item and the database stores the path to that image stored on the server. While I can retrieve all the items without any p ...

The RxJS Map operator may struggle to detect changes in an array that has been

EDIT: My question has been flagged as a duplicate. Despite my efforts to search for a solution, I failed to consider the full context of the issue and wasted hours using incorrect keywords. I have acknowledged the helpful response provided once the mistake ...

The input field does not adhere to the maximum length property

I am working on a React method that is supposed to create an input field with a set maximum length: displayInputField: function(name, placeholder, updateMethod, maxLength) { return ( <div className="form-group form-inline"> ...

What is the best way to store JSON encoded items in an array using square brackets?

Currently, I am utilizing Javascript along with NodeJS to dynamically generate an array of JSON objects. My goal is to store this array of JSON objects in a .json file for future reference. However, when I attempt to save the file, I encounter an issue whe ...

Encountering an error when attempting to parse a JSON Object in Java from an AJAX call

** Latest Code Update ** My JavaScript and Ajax Implementation: $(function() { $("#create_obd").bind("click", function(event) { var soNumber = []; $('#sales_order_lineItems input[type=checkbox]:checked').eac ...

JavaScript Code: Empty a text box when a different one is active

Looking for a solution to clear the content of one textbox when the user interacts with another in HTML and JavaScript. <input id="tb1" type="text" name="textbox1"> <input id="tb2" type="text" name="textbox2"> Seeking JavaScript code that wil ...

Utilizing node.js for manipulating files (JSON) through reading and writing operations

There is an issue with my function that reads a JSON file and updates it using the fs.writeFile method. When I invoke this function multiple times, it fails to update the file properly. After the first call, it adds extra curly brackets at the end of the J ...