Utilizing Angular 4 Typescript to create cascading drop-downs within a table

As a newcomer to Angular, I am in the process of building my first application using Angular 4 and TypeScript.

I would like to implement Cascading dropdowns within a table using Angular 4.

Currently, I am facing an issue where changing the dropdown selection in one row affects all other rows as well.

My goal is to have the second level dropdown in each row update only when the corresponding first level dropdown is changed.

I have some ideas on how to tackle this, but I believe there might be a more elegant solution using Angular methods. Any guidance on achieving this functionality using Angular would be greatly appreciated.

Below is a snippet of the TypeScript code:

import { Component, OnInit, EventEmitter } from '@angular/core';
import { Category } from '../model/Category';
import { SubCategory } from '../model/subCategory';
import { Partner } from '../model/partner';
import { GetdataService } from '../../../../Server/api/Getdata.service';
import { Router } from '@angular/router';

@Component({
  templateUrl: 'UploadFile.component.html'
})
export class UploadFileComponent implements OnInit {
  AllCategoryList: Category[] = [];
  AllSubCategoryList: SubCategory[] = [];
  constructor(private _datatask: GetdataService, private _router: Router) { }

  onChangeCategory(deviceValue) {         
    if (deviceValue > 0) {
      this._datatask.getAllSubCategory(deviceValue).subscribe(
        (data: SubCategory[]) => {
          this.AllSubCategoryList = data;
        }
      );
      console.log("from component: " + deviceValue);
    }
    else
      {
        //clear dropdown...
        this.AllSubCategoryList= [];        
      }
  }

  ngOnInit() {
    this._datatask.getAllCategory().subscribe(
      (data: Category[]) => {
        this.AllCategoryList = data;
      }
    );

    this._datatask.getAllPartner().subscribe(
      (data: Partner[]) => {
        this.AllPartnerList = data;
      }
    );
  }  
}

And here is a snippet of the HTML code:

<div>
  <table width="100%" border="1">
    <thead>     
      <th>Category</th>
      <th>SubCategory</th>
      <th>Partner</th>
    </thead>
    <tbody *ngFor="let transaction of transactions">
      <tr>       
        <td>
          <select style="Width:100px;" (change)="onChangeCategory($event.target.value)" >
            <option value=0>--Select--</option>
                <option  value="{{item.ID}}"  *ngFor="let item of AllCategoryList" [ngValue]="item.ID" >{{item.Category}}</option>
            </select>
        </td>
        <td>
          <select style="Width:100px;">
            <option value=0>--Select--</option>
                 <option  *ngFor="let item of AllSubCategoryList" [ngValue]="item.ID" >{{item.SubCategory}}</option> 
            </select>
        </td>
        <td>
          <select style="Width:100px;">
            <option value=0>--Select--</option>
                <option  *ngFor="let item of AllPartnerList" [ngValue]="item.ID" >{{item.PartnerName}}</option>
            </select>
        </td>
      </tr>
    </tbody>
  </table>
</div>

Any assistance or advice on this matter would be highly appreciated.

Answer №1

It seems that the issue lies in the requirement for an array of states, as mentioned in the provided plunker. This same solution can likely be applied to your original code.

Adjustment made to list-component.ts file:

export class CountryListComponent {

  states: State[] = [[] as State[],[] as State[],[] as State[]] 

  onSelect(value,index) {
    this.states[index] = this._dataService.getStates().
      filter((item)=> item.countryid == value);
  }
}

Edit in list-component.html file:

  • Update: following a discussion on this thread with @GünterZöchbauer :
  • Switched from using (change) to (ngModelChange)

<select [(ngModel)]="selectedCountry[number].id"
    (ngModelChange)="onSelect($event, number)">

Revised Plunker

Answer №2

I encountered a similar issue and was able to resolve it by creating a custom pipe.

To create the filter in an external file, you can follow these steps:

mycustomfilter.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'myCustomFilter',
    pure: false
})
export class myCustomFilterPipe implements PipeTransform {

  transform(items: any[], field : string, value): any[] {
    if (!items) return [];
    if (!value || value.length === 0) return items;
    return items.filter(it =>
    it[field] === value);
  }
}

Include the declarations in your app module like this:

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ App, myCustomFilterPipe],
  bootstrap: [ App ]
})

In your item-order.component.ts file, define your categoryList and itemList arrays:

categoryList=[{id:1,name:'Office Stationery'},
              {id:2,name:'Grocery'}
        ];
itemList=[
         {id:1,name:'Pen',categoryID:1},
         {id:2,name:'A4 Peper',categoryID:1},
         {id:3,name:'Oil',categoryID:2},
         {id:4,name:'Sugar',categoryID:2}
    ];

Within your item-order.component.html file, use the custom filter in the template:

<tr *ngFor="let order of o.controls; let i = index" [formGroup]="order" class="form-row">
              
<td>
<select class="form-control" formControlName="ItemCategoryID">
<option value="">Select</option>
<option *ngFor="let s of categoryList" [ngValue]="s.id">{{s.name}}</option>
</select>
</td>
<td>
<select class="form-control" formControlName="ItemID">
<option value="">Select</option>
<option *ngFor="let s of itemList | myCustomFilter : 'categoryID' : order.value.ItemCategoryID" [ngValue]="s.id">{{s.name}}</option>
</select>
</td>
</tr>

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

The term "angular" is not recognized or defined in

Upon executing gulp in the command line terminal, an error warning appears. I have included the angular.js file in the HTML code but can't pinpoint the issue. Here is the HTML code snippet: <!DOCTYPE html> <html lang="en" ng-app="confusionA ...

Mongoose, Angular, and Express are not functioning properly when using the PUT method

I'm having trouble with implementing a basic edit function in my application. The delete and get functions are working fine, but I keep encountering a 500 error when trying to make a put request. I've attempted using findByIdAndUpdate and FindOne ...

Common mistakes made while working with decorators in Visual Studio Code

Having trouble compiling TypeScript to JavaScript when using decorators. A persistent error message I encounter is: app.ts:11:7 - error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the ' ...

The type 'true | CallableFunction' does not have any callable constituents

The error message in full: This expression is not callable. No constituent of type 'true | CallableFunction' is callable Here is the portion of code causing the error: public static base( text, callB: boolean | CallableFunction = false ...

Accessing instance variables from a chained observable function in Angular 2/Typescript

Currently, I am utilizing Angular2 along with Typescript. Let's assume that there is a dummy login component and an authentication service responsible for token authentication. In one of the map functions, I intend to set the variable authenticated as ...

When trying to click the button in Navbar.jsx, I encounter an error when attempting to invoke the setShowCart(true) function

I've encountered an issue while trying to call the setShowCart(true) function in Navbar.jsx. I'm unsure of how to fix this. import React from 'react' import Link from 'next/link'; import {AiOutlineShopping} from 'react-ic ...

Error encountered when installing angular 8 components due to package conflicts

Having Trouble Building .NET Core + Angular Project I have encountered an unfamiliar project that requires minor fixes. I attempted to build it with the following command: dotnet publish -c Release -r win-x64 --self-contained false --output "D:&bso ...

Combine VS2015 preview with TypeScript 1.3 at your own risk - it may result

After installing VS2015 Preview, I decided to create an MVC project and add a new TypeScript file. However, when trying to compile, I encountered the following error message: The "TypeScript.Tasks.VsTsc" task could not be loaded from the assembly C:&bso ...

Exploring an Angular Real-World Example Application on Github - Resolving the Following Bug

my surroundings. export const environment = { production: false, api_url: 'localhost:3306/api' }; my personal server is at localhost:3306 (MAMP) The instructions provided are to edit src/environments/environment.ts in order to ch ...

Leveraging AngularJS for retrieving the total number of elements in a specific sub array

I'm currently working on a to-do list application using Angular. My goal is to show the number of items marked as done from an array object of Lists. Each List contains a collection of to-dos, which are structured like this: [{listName: "ESSENTIALS", ...

The ng-if directive in AngularJS seems to be malfunctioning

Could someone please help me understand why my "Voted:" checkbox is not controlling the ng-if directive? Strangely enough, the "Keep HTML" checkbox is working fine. <p> <li ng-repeat="x in info"> {{x.name}} Voted: <input type="c ...

Incorporating Datatables into Django for optimized data presentation

As a newcomer to web development, I'm unsure how to incorporate dataTable in a Django project with my json data for displaying it in a table using DataTable. I've successfully created a Django project and set everything up properly. However, I h ...

Guide on how to showcase the template by leveraging the roomList information with ngTemplateOutlet in Angular

TS roomList = [{ name: 'Room2' }] HTML <div class="Layout-body"> <ng-container *ngFor="let dt of roomList; index as i" [ngTemplateOutlet]="Room1" [ngTemplateOutletContext]="{ data: dt, i: i }&qu ...

Guide to establishing a primary filter for my Json information with Angular.js?

After spending multiple days searching and reading, I am struggling to set an initial value for the data from a Rails JSON file in my application. The app focuses on incident tickets, and although I am able to retrieve all entries from the database using d ...

Gather information from Django and Angular APIs via RESTful requests

Trying to access the json data from a Django-powered rest api. The data can only be found at: Encountering an error when attempting to fetch it using: $http({ method: 'GET', url: 'http://127.0.0.1:8000/xyz', ...

Is AngularJS the right choice for developing this application?

Recently, I've come to the realization that I want to dive into the world of AngularJS framework after working with jQuery for several years. I have a vision of developing an application that allows users to easily modify webpage DOM using a browser- ...

Experience the dynamic live preview feature of Sanity integrated with NextJS 13

I am facing an issue with checking if preview mode is activated on my website. While following a YouTube tutorial, I realized that the instructions may be outdated with the latest NextJS update. This was the code snippet I was originally working with to ...

Pass data from Angular UI Bootstrap Modal to parent controller upon background click or closing with the ESC key

Hello everyone. Let's dive right into the issue - I am trying to figure out how to pass a variable back from an AngularJS UI Boostrap Modal when the user clicks on the background or presses the ESC button on their keyboard. There are some solutions ...

Exploring AngularJS and Jasmine for testing a factory component

I am currently learning about unit testing in AngularJS. I have a factory that I am trying to spy on using Jasmine, but I am having trouble figuring out the correct syntax for the test spec. Below is the code snippet for the factory: app.factory('ass ...

How can you utilize Angular Signals in combination with HostBinding to dynamically update styles?

Within a component called app-test, the following code is present: @Input({ transform: booleanAttribute }) reverse: boolean = false; @HostBinding('style.flex-direction') direction: string = this.reverse ? 'column-reverse' : &ap ...