Angular click event: how to select a checkbox within an a element?

13.4k Views Asked by At

In my Angular app I have the following menu:

enter image description here

As you can see I have items (that are a elements) and a checkbox and a label in each of them:

<span class="caption">RAM</span>
<a class="item">
    <div class="item-checkbox">
        <input type="checkbox" tabindex="0" class="hidden">
        <label>4 GB</label>
    </div>
</a>
<a class="item">
    <div class="item-checkbox">
        <input type="checkbox" tabindex="0" class="hidden">
        <label>8 GB</label>
    </div>
</a>
<a class="item">
    <div class="item-checkbox">
        <input type="checkbox" tabindex="0" class="hidden">
        <label>16 GB</label>
    </div>
</a>

How should I add (click) to every item to correctly handle event capturing so if user click on label or on whole item I get the related checkbox selected?

...Or do you know a better way to reach what I mean?

5

There are 5 best solutions below

2
ConnorsFan On BEST ANSWER

To make sure that clicking on the label toggles the checkbox, include the input element inside of the label (as explained in MDN):

<a class="sub-item item">
  <div class="item-checkbox">
    <label><input type="checkbox" tabindex="0" class="hidden">4 GB</label>
  </div>
</a>

If you also want the label to fill the anchor element, define the CSS as shown below. With this styling in place, clicking on the anchor will toggle the checkbox.

.ui.secondary.menu a.item {
  padding: 0px;
}

div.item-checkbox {
  width: 100%;
  height: 100%;
}

div.item-checkbox > label {
  display: block;
  padding: .78571429em .92857143em;
}

div.item-checkbox > label > input {
  margin-right: 0.25rem;
}

See this stackblitz for a demo.

3
Nico Schuck On

First of all you should use *ngFor to list all your options:

html:

<a class="item" *ngFor="let choice of checks; let i=index">
    <div class="item-checkbox">
        <input type="checkbox" tabindex="0" class="hidden" [value]="choice.value" (change)="onCheckChange($event)">
        <label>{{choice.title}}</label>
    </div>
</a>

component:

public checks: Array<choices> = [
  {title: '4 GB', value: '4'},
  {title: "8 GB", value: '8'},
  {title: "16 GB", value: '16'}
];

public onCheckChange(event) {
    // do some things here
}

Further, you should use Reactive Forms to validate your choices: https://angular.io/guide/reactive-forms

1
Himanshu Singh On

You have to create a boolean array and bind this to your checkboxes.

.ts file

  myArray: any[] = [
 {
      "size": "2GB",
      "value":false
    },
    {
      "size": "4GB",
      "value":false
    },
    {
      "size": "8GB",
      "value":false
    }
]

.html file

<div *ngFor="let data of myArray">
 <a class="item">
    <div class="item-checkbox">
        <input type="checkbox" tabindex="0" class="hidden" [(ngModel)]="data.value" (ngModelChange)="changeHandler()">
        <label>{{data.size}}</label>
    </div>
 </a>
</div>

Working demo : link

2
Felipe Malara On

You could do something like that:

const ramOptions = [
  {
    id: 1,
    size: '4 GB'
  },
  {
    id: 2,
    size: '8 GB'
  },
  {
    id: 3,
    size: '16 GB'
  }
]

And in html:

<a class="item" *ngFor="let option of ramOptions">
    <div class="item-checkbox">
        <input type="checkbox" tabindex="0" class="hidden" (change)="onSelect(option.id)">
        <label>{{option.size}}</label>
    </div>
</a>

If in the .js/.ts file, you can create an interface to define the handler. Just as:

onSelect(id: string) {
  ...
}
1
Addis On

If you can place all the checkboxes in a container, you can set a single click event listener on the container, and event.target will give you the clicked element and previousElementSibling will select the sibling input.

function doSomething() {
    const selectedInput = event.target.previousElementSibling;
    selectedInput.checked = selectedInput.checked? false : true;
}

But in case there is a probability that you document structure changes in the future, say for example, if other elements get in between the input and the label, or their order changes, then the sibling selector will fail. To solve this you can use a parent selector instead and select the chechbox input element inside of it.

document.getElementById('container').addEventListener('click', doSomething);

function doSomething() {
    const selectedElement = event.target.parentElement.querySelector('input[type="checkbox"]');
    selectedElement.checked = selectedElement.checked? false:true;
}
<div id= 'container'>
  <span class="caption">RAM</span>
  <a class="item">
      <div class="item-checkbox">
          <input type="checkbox" tabindex="0" class="hidden" value="4 GB">
          <label>4 GB</label>
      </div>
  </a>
  <a class="item">
      <div class="item-checkbox">
          <input type="checkbox" tabindex="0" class="hidden" value="8 GB">
          <label>8 GB</label>
      </div>
  </a>
  <a class="item">
      <div class="item-checkbox">
          <input type="checkbox" tabindex="0" class="hidden" value="16 GB">
          <label>16 GB</label>
      </div>
  </a>
</div>