Subscribing to valueChanges in reactive forms to dynamically update checkbox options

My goal is to create a select dropdown with options for bmw, audi, and opel. The user can only select one option from the dropdown, but they should also have the ability to select the options that were not chosen using checkboxes.

cars = [
    { id: 1, name: 'bmw' },
    { id: 2, name: 'audi' },
    { id: 3, name: 'opel' }
];

Here's how it should work:

For instance, if the user selects bmw in the dropdown, then two checkboxes for audi and opel should be displayed since those are the remaining options. If the user changes their selection from bmw to something else, the checkboxes should update accordingly to display the available options.

Form setup:

this.firstStepForm = this.fb.group({
  cars: [''], // select
  models: this.fb.array([]) // checkboxes
});

Setting up checkboxes:

private setupControls(details: any): void {
let control = <FormArray>this.firstStepForm.controls.models;

details.forEach(x => {
  control.push(this.fb.group({
    id: x.id,
    name: x.name
  }))
})

Subscribing to changes:

this.firstStepForm.get('cars').valueChanges.subscribe((carId: number)

Check out a simple example on stackblitz

I am currently trying to figure out how to determine the index of the selected car and update/remove the checkboxes accordingly.

Desired Results:

  1. Checkboxes should display only the options that were not selected in the dropdown
  2. If the selected value changes, checkboxes should update to show the remaining options.

Queries:

Is there a simpler way to achieve this without using removeAt (FormArray)? Maybe I could use underscoreJs _filter function to filter out values based on the id, but how do I filter out FormArray items based on a specific value (:id)?

let magic = _.filter(arr, function (num) { return num != carId });

console.log('magic: ', magic);

Answer №1

give it a shot:

export class AppComponent implements OnInit {
  vehicles = [
    { id: 1, name: 'toyota' },
    { id: 2, name: 'honda' },
    { id: 3, name: 'ford' }
  ];
  firstStepForm: FormGroup;
  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.buildFirstStepForm();
    this.firstStepForm.get('vehicles').setValue(this.vehicles[0].id);
    this.onChange(this.vehicles[0].id); // initial first item select
  }

  onChange(e){
    let arr = this.vehicles.filter(item => item.id != e);
    this.models.controls = [];
    this.setupControls(arr)
  }

  get models(): FormArray {
    return <FormArray>this.firstStepForm.controls.models;
  }

  private buildFirstStepForm(): void {
    this.firstStepForm = this.fb.group({
      vehicles: [''],
      models: this.fb.array([])
    });
  }

  private setupControls(details: any): void {
    details.forEach(x => {
      this.models.push(this.fb.group({
        id: [x.id],
        name: [x.name]
      }))
    })
  }
}

html:

<form [formGroup]="firstStepForm" (ngSubmit)="submit()">
    <p>Choose:</p>
    <select formControlName="vehicles" (change)="onChange($event.target.value)">
        <option *ngFor="let vehicle of vehicles; let i = index" [value]="vehicle.id">
            {{vehicle.name}}
        </option>
    </select>
  <br>
  <br>
  <br>
  <p>Options:</p>
  <div class="form-check" *ngFor="let type of models.controls; let i = index">
    <label formArrayName="models">
      <input type="checkbox">{{type.value.name}}
    </label>
  </div>
</form>

DEMO

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 flow union type operates smoothly without any errors occurring

In the code snippet below, I have defined a type 'Something' which can have three possible values: 'A', 'B', or 'C'. The function 'f' takes an object of type Something as input and returns a string based on ...

Currently in the process of optimizing controllers but continuously encountering 404 errors when making api requests

I previously utilized the SampleData controller that is automatically generated. I added my custom methods, everything was functioning perfectly. Recently, I decided to create a new class for better organization purposes. After pasting in the desired metho ...

Typescript encounters issues when assigning declaration as TRUE

Currently, I'm working on a project in Angular 2 and attempting to create TypeScript definitions for it so that it can be exported as a library. I have various services set up that make HTTP requests to components, all structured similarly to the cod ...

Setting up an Ionic 5.24 / Capacitor 2.0.1 / Angular 9.1.2 project to view TypeScript sources while debugging in AVD using Chrome DevTools

I'm having trouble configuring an Ionic (5.24) project to access the TypeScript sources while debugging on an Android Virtual Device using Chrome DevTools. Capacitor version: 2.0.1 Angular version: 9.1.2 Here's what I have tried: ionic cap ru ...

Angular 5 ngIfElse: How to save the outcome of a condition in a storage container

Code Snippet: <mat-icon [ngClass]='{ rotate: !users }'>refresh</mat-icon> <div *ngIf="usersObservable | async as users; else loading"> ... </div> <ng-template #loading let-users> Waiting... </ng-template> ...

Creating a personalized attribute directive within Angular2

I've been attempting to apply a custom attribute directive to an input element, but I'm struggling to achieve it. Here is my directive code: @Directive({ selector: '[disable-paste]' }) export class DisablePaste { constructor(p ...

Best practices for safely handling dynamic keys in Typescript

I am searching for a secure method to create keyed objects in this manner: interface Types { RED: 'RED'; BLUE: 'BLUE'; GREEN: 'GREEN'; } type TypeKeys = keyof Types; const COLORS: Types = { RED: 'RED', B ...

Troubleshooting form submission issues in Angular 4

I am encountering a few issues with my search form. It is supposed to function as a search tool with one input field and one button. However, something seems amiss. I am utilizing an API that returns values based on the string inputted. When an empty value ...

Validating specific controls in an Angular 2 FormGroup and marking them as invalid

Currently, I have implemented an Angular 2 Reactive form using FormGroup. The main requirement is to compare the values of two fields, for which I have included a validator in the FormGroup during creation. The validation process seems to be working effect ...

Getting the readonly-item type from an array in TypeScript: A step-by-step guide

Is it possible to create a readonly item array from a constant array? const const basicValueTypes = [{ value: 'number', label: 'Number' },{ value: 'boolean', label: 'Boolean' }]; type ReadonlyItemArray = ??? ...

In order to maintain a custom tooltip in an open state until it is hovered over, while also controlling its

When hovering over the first column of the table, a tooltip will appear. Within each material tooltip, I would like to include a button at the bottom right after the JSON data. When this button is clicked, it should open an Angular Material dialog. <ng ...

Angular Throws 'Expression Changed After Check' Error When Behavior Subject is Triggered

In my Angular 11 project, I am utilizing a BehaviorSubject to update the toolbar content from various components. The toolbar subscribes to the BehaviorSubject in the following manner: <breadcrumbs [crumbs]="messageService.getBreadcrumbs() | async& ...

What is the best way to establish a restriction on the number of items obtained from an RSS

I am receiving a feed from this specific link. My goal is to only retrieve the initial five items from the feed, but currently I am getting all of the items. Is there a way for me to specifically request only the first five items? Do I need to include an ...

There is no corresponding version available for [email protected] in Angular 6

After cloning a project from git, I attempted to run npm install. However, an error message popped up, as shown in the following link: https://i.stack.imgur.com/pqYbK.png Can someone please explain why this is happening and how I can resolve it? Any help ...

Transitioning from Angular2 beta15 to beta16

After updating my package.json and running npm install, I encountered this error while trying to launch my app in the browser: angular2-polyfills.min.js:1 Unhandled Promise rejection: Error: Attempting to create a class provider but "undefined" is not a c ...

Splitting Angular modules into separate projects with identical configurations

My Angular project currently consists of approximately 20 different modules. Whenever there is a code change in one module, the entire project needs to be deployed. I am considering breaking down my modules into separate projects for individual deployment. ...

The Tanstack react-table feature is limited in its ability to output tsx from the cell

Currently conducting a test on Tanstack react-table library using React and TypeScript. It appears that I am encountering an issue with returning tsx/jsx from the cell function of ColumnDef: Is there something crucial that I seem to be overlooking in this ...

Can you guide me on how to record a value in Pulumi?

According to Pulumi's guidance on inputs and outputs, I am trying to use console.log() to output a string value. console.log( `>>> masterUsername`, rdsCluster.masterUsername.apply((v) => `swag${v}swag`) ); This code snippet returns: & ...

Functionality not functioning within Shadow DOM

After creating and exporting an Angular Element as a single script tag (user-poll.js), using the element on a host site is simple. Just include the following two lines: <user-poll></user-poll> <script src="path/to/user-poll.js"></sc ...

Is it more efficient to wait for the server to respond, or should I update the client immediately

Today, I found myself contemplating an interesting question. As I work on developing a Single Page Application (SPA) using Angular, I am focusing on creating a calendar module similar to Google Calendar. This module will allow users to add, edit, and remov ...