How can I store unique and only selected checkbox values in an array using Angular?

I need assistance with creating an array from three checkboxes. The array should only contain the values of the checked checkboxes and should not include duplicates.

I have attempted to achieve this functionality, but the values are still being added regardless of whether they are checked or not.

If anyone can identify the issue in my code, I would appreciate it.

.ts

public dataSource: any[] = [];

compsForm: FormGroup = new FormGroup({

  dataSource: new FormControl('', Validators.required),
  name: new FormControl('',Validators.required),
});
    dataSourceChange(event:any){
    
        var name = event.target.name;
        var isChecked = event.target.checked;
        const index = this.dataSource.findIndex((el) => el.id === name);
    
        if (index > -1) {
          this.dataSource[index].isChecked = isChecked;
        } else {
          this.dataSource.push(name);
        }
        this.dataSource = [...this.dataSource];
        console.log(this.dataSource);
      }

.html

<form [formGroup]="compsForm">
     <input type="checkbox" name="om" (change)="dataSourceChange($event)" formControlName = "dataSource"> <span> OM</span>
     <input type="checkbox" name="fe" (change)="dataSourceChange($event)" formControlName = "dataSource"> <span> FE</span>
     <input type="checkbox" name="be" (change)="dataSourceChange($event)" formControlName = "dataSource"> <span> BE </span>
</form>

Answer №1

Here are some important points to keep in mind:

Make sure that the formGroup in your TypeScript file matches the structure of the form in the HTML. If your HTML form has 3 inputs, then your formGroup should have 3 corresponding fields. Each input in the HTML should have a unique name.

If you are only adding elements to an array without removing them when they are unchecked, the array will continue to grow indefinitely.

When dealing with potential duplicate entries, consider using a "Set" data structure and then converting it into an array once you have finished processing all the data.

For more information on HashSet, check out this Stack Overflow answer: HashSet Explanation

.html

    <form [formGroup]="compsForm">
  <input
    type="checkbox"
    name="om"
    (change)="dataSourceChange($event)"
    formControlName="dataSource1"
  />
  <span> OM</span>
  <input
    type="checkbox"
    name="fe"
    (change)="dataSourceChange($event)"
    formControlName="dataSource2"
  />
  <span> FE</span>
  <input
    type="checkbox"
    name="be"
    (change)="dataSourceChange($event)"
    formControlName="dataSource3"
  />
  <span> BE </span>
</form>

.ts

     // private _dataSource: any[] = [];
  private _dataSet: Set<string> = new Set<string>();
  private _dataArray = [];

  compsForm: FormGroup = new FormGroup({
    dataSource1: new FormControl(''),
    dataSource2: new FormControl(''),
    dataSource3: new FormControl(''),
  });

  dataSourceChange(event: any) {
    console.log(event.target.name);

    const name = event.target.name;
    const isChecked = event.target.checked;

    if (isChecked) this._dataSet.add(name);
    else this._dataSet.delete(name);

    this._dataArray = Array.from(this._dataSet);
    console.log(this._dataArray);
  }

Answer №2

The concept originates from this Stack Overflow post (specifically the section with a simple example using a variable). By replacing the variable "answer" with the formControl, you can easily modify it.

<div *ngFor="let option of options">
  <input
    #check
    type="checkbox"
    [checked]="compsForm.get('dataSource').value &&
               compsForm.get('dataSource').value.indexOf(option) >= 0"
    (change)="onChange(option, check.checked)"
  />

  {{ option }}
</div>

options=["check 1","check 2","check3"]
compsForm: FormGroup = new FormGroup({

    dataSource: new FormControl('', Validators.required),
    name: new FormControl('',Validators.required),
});
onChange(option:string,checked:boolean)
{
     let answer=this.compsForm.get('dataSource').value || [];
     if (checked && answer.indexOf(option)<0)
     {
         answer=[...answer,option]
         .sort((a,b)=>this.options.indexOf(a)>this.options.indexOf(b)?1:-1)
     }

    if (!checked)
          answer=answer.filter(x=>x!=option)

    this.compsForm.get('dataSource').setValue(answer.length?answer:null)
}

View the code in action on StackBlitz

Please note: If you only require the code snippet, consider using a getter method

get dataSourceValue(){
   return this.compsForm.get('dataSource').value
}

Update: Revise options as an array with value and label

If we have something like

options2 = [
    { value: 'check1', label: 'Check 1' },
    { value: 'check2', label: 'Check 2' },
    { value: 'check3', label: 'Check 3' },
];

We need to make a few adjustments to the code

<div *ngFor="let option of options2">
  <input
    #check
    type="checkbox"
    [checked]="compsForm2.get('dataSource').value &&
               compsForm2.get('dataSource').value.indexOf(option.value) >= 0"
    (change)="onChange2(option.value, check.checked)"
  />
  {{ option.label }}
</div>

Observe how we pass the function option.value and reference .value.indexOf(option.value)

Our updated function becomes

  onChange2(option: string, checked: boolean) {
    let answer = this.compsForm2.get('dataSource').value || [];
    if (checked && answer.indexOf(option) < 0) {

      //utilize "optionsValue" for easier sorting
      const optionsValue = this.options2.map((x) => x.value);

      answer = [...answer, option].sort((a, b) =>
        optionsValue.indexOf(a) > optionsValue.indexOf(b) ? 1 : -1
      );

    if (!checked) answer = answer.filter((x) => x != option);

    this.compsForm2.get('dataSource').setValue(answer.length ? answer : null);
    this.compsForm2.get('dataSource').markAsTouched();
  }

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

Maximize the efficiency of an integer array in C++

My data consists of a 2D array of int16_t values. int16_t my_array[37][73] = {{**DATA HERE**}} The range of these values spans from just above to just below the limit of int8_t, with some repetition. I am looking to optimize this lookup table by reducing ...

Tips for setting up a websocket connection between angular-socketio and flask-socketio

As a newcomer to web sockets, I am currently working on implementing a web socket server using flask-socketio for the server and angular-socketio for the client-side. For the server side in Flask, this is the code snippet I am using: application.py @ ...

Can Primeng and Angular2 be integrated into JSF without the use of npm?

I'm looking to implement the Angular2 framework for my frontend development, and I've decided to use PrimeNG for the UI components. However, I am not familiar with how npm functions. Here are some tech details: I will be using Eclipse or NetBe ...

The in_array() function in PHP is always reliable

Issue resolved! Special thanks to Barmar for providing comments that guided me in the right direction. Here is the updated code snippet reflecting the changes made. I have now enclosed everything within the in_array conditional instead of having it insid ...

"Alert in Javascript executing prematurely prior to initiating the function for sending a get request

private validateURL(url: string) { let isValid = false; this.$http.get(url).then( (data) => { console.log('success'); isValid = true; } ).catch( (reason) => { console. ...

What is the best way to incorporate a JavaScript library into my Angular 2 project?

I successfully installed Tween js using npm install tween, but I am unable to import it into my component. The library is located in node_modules/tween. I have tried: import * AS TWEEN from 'tween/tween.js' import {TWEEN} from 'tween&apos ...

How Keyof can render an object undefined and prevent accurate verification

Encountering TS2532 error: Object is possibly 'undefined' while attempting to access an object's value by dynamically selecting the key. TypeScript seems to be restricting me from checking the field values, and I'm unsure of the underly ...

How to access type properties in typescript without using the "this" keyword

Below is a snippet of code that I am working with: class Player implements OthelloPlayer { depth; constructor(depth: number) { this.depth = depth; } getMove(state: OthelloState) { return this.MinimaxDecision(stat ...

What is the best way to send a string parameter from an Angular UI to a Node.js backend?

My goal is to transfer a string value from an Angular UI to a Node.js backend API, which will then search in MongoDB using the provided string value as shown below. I am attempting to receive input in enteredValue and pass it on to the http.get call as pa ...

Using es6 map to deconstruct an array inside an object and returning it

I am looking to optimize my code by returning a deconstructed array that only contains individual elements instead of nested arrays. const data = [ { title: 'amsterdam', components: [ { id: 1, name: 'yanick&a ...

Ensure the modal is closed when the user clicks on the Finish button within Docusign

I have a Docusign sign URL displayed in an iframe on my webpage. When the user clicks on FINISH, I want to close the modal iframe instead of redirecting to another page within the iframe. Please refer to the screenshot below for more clarity: I am implem ...

Adding two double arrays together using AVX vectorization technique

I'm looking for a way to add the elements of two double arrays together and store the result in a third array. Currently, I have the following simplified function: void add( double* result, const double* a, const double* b, size_t size) { memcpy( ...

The functionality of CSS transitions may be affected when dynamically adding a class

Creating a custom CSS for my main div: .main { height: 0%; position: absolute; width: 100%; z-index: 100; background: whitesmoke; bottom: 0; border-radius: 15px; padding: 20px; color: gray; left: 0; right: 0; transition: height 1s e ...

I keep seeing "Uncaught TypeError: Unable to retrieve property 'get' from undefined" error message popping up

Currently, I am attempting to retrieve a JSON from a separate microservice (local) utilizing a different port. There is uncertainty as to whether the issue lies within my configuration or the microservice itself. Despite successfully displaying the JSON on ...

A guide on utilizing the useEffect hook to dynamically update a button icon when hovering over it in a React application

Is it possible to change the icon on a button when hovering using useEffect? <Button style={{ backgroundColor: "transparent" }} type="primary" icon={<img src={plusCart} />} onCl ...

Error encountered in Angular/Ramda while using mapAccum with an array of objects in Typescript

I am having difficulties implementing Ramda in an Angular 6 / TypeScript environment. "ramda": "^0.25.0", "@types/ramda": "^0.25.24" This is how I have started: const addP = (p1,p2) => ({ x: p1.x+p2.x,y: p1.y+p2.y }); const accum = (a,b) => [add ...

Find the missing number within an array using PHP

Is there a way to search for missing numbers in an array of IDs retrieved from a database? The IDs are numbers themselves. For example, if we have: $id=array(0,1,3,6,7);, some data may be missing due to deletions or updates. In this case, I need to search ...

Angular 2's latest release, RC.5, introduces an indispensable singleton global shared

I am currently working on implementing global singleton services. I came across this solution - https://angular.io/docs/ts/latest/guide/ngmodule.html#!#shared-module, but unfortunately it is not working for me. Here's a simplified version of my share ...

Error: Unable to locate specified column in Angular Material table

I don't understand why I am encountering this error in my code: ERROR Error: Could not find column with id "continent". I thought I had added the display column part correctly, so I'm unsure why this error is happening. <div class="exa ...

Optimizing Angular 2+ performance with a custom minification of the

I've taken note of the cautions regarding avoiding pipes for ordering/sorting. While I understand the concerns with impure pipes, I'm not entirely clear on the issue with minification. The documentation and various posts highlight the potential ...