简体   繁体   中英

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

In my Angular app I have the following menu:

在此处输入图片说明

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?

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

<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.

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>

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

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

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) {
  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM