0

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 Answers 5

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

This looks to be the best answer. Anyway how to extend click to the a element? So clicking on the a will toggle the checkbox. Please have a look at my stackblitz: stackblitz.com/edit/semantic-ui-udkfhf. Thank you
I updated the answer and the stackblitz to make sure that clicking on the anchor toggles the checkbox.
1

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>

1 Comment

I was not clear, sorry for this. I'm talking about "event capturing". I have edited my question. In your snippet if you click on label or on whole item I don't get related checkbox selected.
0

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

3 Comments

Yes, I'm using ReactiveForms and, yes, I'm using *ngFor. The code in my question is just a sample... Anyway, I was not enough clear, I have edited my question. Please read it again. Thank you!
If you just want that your span is also triggering the whole checkbox, how about to use material.angular.io/components/checkbox/overview?
I'm not using Material.
0

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

1 Comment

I was not clear, sorry for this. I'm talking about "event capturing". I have edited my question. In your snippet if you click on label or on whole item I don't get related checkbox selected.
0

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

2 Comments

I was not clear, sorry for this. I'm talking about "event capturing". I have edited my question.
You could put the function call on the <a> element

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.