Guide to building interactive dropdown menus in Angular 8

In my user interface, each row contains three dropdowns for level 1, level 2, and level 3, as well as an "Add Level" button.

When the "Add Level" button is clicked, a new set of three dropdowns for level 1, level 2, and level 3 should be added dynamically to the same row with each click, without affecting other rows.

I need help modifying my current code to achieve this desired functionality.

Link to StackBlitz Code

Please see the attached image for reference on how the level 1, level 2, and level 3 dropdowns should look like.

https://i.sstatic.net/NTg5N.png

Answer №1

It's a familiar routine. When controlling an object with ReactiveForms, the approach is consistent: create a FormGroup for single objects and a FormArray for arrays. For arrays representing objects, use a FormArray of FormGroup; for other arrays, simply use a FormArray.

The initial step involves defining the structure of your data. Considering that "levels" is an array, your data can be organized as follows:

{
  "plannedProduction": 210468,
  "factORLossTree": [
    {
      "skuid": "000000000034087070",
      "skuDescription": "SUNLIGHT DESTINY HW PWD YELLOW 8X900G",
      "productionOrderNo": "X49033251",
      "category": "Fabric Cleaning",
      "levels": [
        {
          "level1": "",
          "level2": "",
          "level3": ""
        }
        ....
      ]
    },
    {
      "skuid": "000000000067141695",
      "skuDescription": "SUNLIGHT DESTINY YELLOW 24X170G",
      "productionOrderNo": "X49039793",
      "category": "Fabric Cleaning",
      "levels": [
        {
          "level1": "",
          "level2": "",
          "level3": ""
        }
        ....
      ]
    },
    ....
   ]
}

For easy access to a FormArray in your code, utilize a getter (*) like this:

get lossFormArray() {
  return this.orLosstreeForm.get('factORLossTree') as FormArray;
}

For accessing a nested FormArray within another FormArray, define another "getter" function where you need to provide the index of the formArray as an argument:

getLevels(index:number)
{
  return this.lossFormArray.at(index).get('levels') as FormArray;
}

Additionally, you can implement an auxiliary function to retrieve the value of the formArray at a specific index, simplifying your .html file:

getItemValue(index:number)
{
  return this.lossFormArray.at(index).value;
}

Lastly, include a function to create the FormGroup "level" successfully:

createLevel() {
  return this.fb.group({
    level1: [''],
    level2: [''],
    level3: [''],
  });

When updating the formGroup by calling setData, make sure to adjust the function to accommodate the new FormGroup creation logic:

setData() {
  const resp = {...}
  // Rest of the existing logic here...
}

And the function createLevelItem should look as below:

createLevelItem(data) {
  const formgrp = this.fb.group({
    skuid: ['', Validators.required],
    ...
    levels: this.fb.array([this.createLevel()]),
  });
  if (data !== null) {
    formgrp.patchValue(data);
  }
  return formgrp;
}

This lengthy process leads us to the .html part, demonstrating how to create a series of mutually exclusive dropdowns within a table. Despite the complexity, taking it slow will help in grasping the concept effectively. Let's look at a snippet:

Patiently navigate through the instructions highlighted above to implement and understand the complete functionality efficiently.

Check out the final stackblitz here.

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

JavaScript and HTML code for clipboard functionality without the need for Flash

My challenge lies in creating a grid with numerous columns and data. The user has expressed the desire for a copy to clipboard button that will allow them to easily copy the data. Can anyone suggest ways to implement Copy to Clipboard functionality withou ...

Include a text input field within the multipleTextBox component

How do I select a file and turn it into an option? For example, if there is a file on a server or my desktop, What is the best way to create a function that can handle this? Is AJAX the solution? <input type="text" name="name" value="text " ...

"Problem encountered when using Window.print() in Chrome on an iPad while displaying in a pop-up window created using

My code works perfectly in all browsers and operating systems, except for iPad Chrome. Can anyone help me troubleshoot this issue? <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ...

Issue arises when attempting to use the useEffect hook in React with Typescript to reset states upon the component unmounting

I'm facing an issue with my useEffect cleanup when the component unmounts and setting states simultaneously. My code involves selecting a client by clicking on them and setting their ID to send in an API request: const setClient = () => { setC ...

What is the best way to implement momentJS globally in VueJS 2?

Currently working with Vue.js version 2.6.11 Trying to set up in main.js as follows: import moment from 'moment' moment.locale('nl'); Object.definePrototype(Vue.prototype, '$moment', { value: moment }); Encountering an error ...

obtain the present date using JavaScript

I am currently utilizing the Datetimepicker developed by XDAN. My goal is to have the current date set as the default when the page loads. To achieve this, I attempted using the new Date() along with the getUTCFullYear functions. However, there's a ...

What causes the button size to change in Bootstrap when switching to a spinner?

Every time I switch from a spinner back to a button, the button's size changes. I am struggling to identify the cause of this issue. function resizeButton() { var btn = document.getElementById('submitBtn'); btn.innerHTML = ' ...

Obtain the data from a nested array

I'm facing a situation where I have the following code: var obj = { level1 : { level2 : 'value' } }; I also have another object: var returnData = { value: "level1.level2", anotherThing: "level1" }; The goal is to ...

ERROR: Module 'app/home/home.module' Not Found - Unhandled Promise Rejection

Currently attempting to implement lazy loading of Angular 2 modules using the router, encountering the following error: error_handler.js:50 EXCEPTION: Uncaught (in promise): Error: Cannot find module 'app/home/home.module' Have tried various ...

In Javascript, have an audio clip play every 30 seconds

My webpage has a unique feature - it automatically plays a short audio clip as soon as the page loads. This functionality is achieved using a special audio player called nifty player. Here is the code snippet for embedding the player: <object classid= ...

My React project is altering the direction of my image

Below is the code snippet used to retrieve the user's favorite products import React, { useEffect, useState } from "react"; import { Pagination, Row } from "react-bootstrap"; import { useDispatch, useSelector } from "react-red ...

"Troubleshooting: Issue with AngularJS ng-click Functionality Not Working on Re

Having trouble with the ng-click function in AngularJS when using the following HTML code: <tr ng-repeat="ai in alert_instances" ng-click="go('/alert_instance/{{ai.alert_instancne_id}}')"> <td>{{ai.name}}</td> <td>{{a ...

Selecting an option with a specific index in Angular 2 RC2

I have encountered a situation where the select options are non-unique, with the same value representing different things. This is how our data is structured and I need to work within those constraints. <select id="mySelect"> <option value = "1 ...

Is there a JavaScript method for opening a new window regardless of the PHP file being used?

I have encountered a small dilemma that is causing me frustration. Currently, I have set up a BUTTON on my website. This button, when clicked, triggers a JavaScript function to open a "New Window". The code for this button and function looks like this : ...

Close overlay panel in PrimeFaces calendar

One of the components I’m currently working with is an overlayPanel that contains a calendar. Here's a snippet of the code: <p:overlayPanel hideEffect="fade" showCloseIcon="true" dismissable="true" > <h:form> <p:p ...

Tips on concealing modal popup when the page refreshes successfully

I implemented a progress modal popup to show progress for page reloads. This script is set to the master page and injects the progress modal popup when the form submit event is fired: <script type="text/javascript"> function ...

Update the CSS styles using jQuery

I am looking to update the content within a CSS tag using jQuery. In this instance, I need to change "My content" to "New Content". Here is the CSS code I have: a.appari:focus:after{ background: #333; background: rgba(0,0,0,.8); border-radius: 5px ...

An easy guide on utilizing ngSwitch for datatype selection in Angular

While working in angular2, I came across a question regarding the usage of ngSwitch to load <div> tag based on the datatype of a variable. Is it possible to achieve something like this: <div [ng-switch]="value"> <p *ng-switch-when="isObj ...

Exploring the Document Object Model to locate the adjacent sibling of a parent element

If I need to implement an event that hides the section .dependent-box whenever the element with class .radio-click-hide is clicked, what would be the best approach for traversing the elements to achieve this functionality? I have attempted the following co ...

When attempting to execute Protractor tests, an error occurs stating that the object #<Object> does not possess the 'getInstance' method

Whenever I try to run my Protractor tests from the command line, all of them fail because the protractor object does not have the necessary methods. The error message I receive is: TypeError: Object # has no method 'getInstance' Although this ...