How to trigger checkbox checked event on parent click


#1

I have a number of boxes, each of them contains one checkbox. I needed to update the array if the checkbox is checked, which I achieved by this code:

<div class="col-xs-6 col-md-4 sampleWrapper" *ngFor="let sample of samplesInfo | matchSelectedType:selectedSampleTypeForModal; let i=index">
                    <div (click)="testAlert(sample, $event)" class="sample">
                        <img src="{{ imagesFolder + sample.image }}" class="b1 img-responsive">
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" name="{{ sample.name }}" [value]="sample" [checked]="sample.checked" id="{{i}}" (change)="updateSelectedSamplesArray(sample, $event); sample.checked = !sample.checked;"> {{ sample.name }}
                            </label>
                        </div>
                    </div>
                </div>
// put all selected samples into array
    updateSelectedSamplesArray(obj, event) {
        let index = this.selectedSamplesArray.indexOf(obj);
        if (index === -1) {
            if (event.target.checked) {
                return this.selectedSamplesArray.push(obj);
            }
        } else {
            if (!event.target.checked) {
                return this.selectedSamplesArray.splice(index, 1);
            }
        }
    }

But now I need to do the same thing when the parent div is clicked (the one with the classname of “sample”). How can I do this? Obviously, the $event differs in parent div click and on checkbox change, so I can’t reuse my updateSelectedSamplesArray function.

Regards,
Olga


#2

Hi Olga,

There are a few problems with your code.

  1. you use input when you should be using ion-checkbox

  2. you don’t close your input tag; see this page to copy and paste working code

  3. your code relies on both [checked] and [value], but it should only use [checked]

  4. your (change) code does 2 actions: it calls a function as well as executes in-line code; for simplicity’s sake & for the readability of the code, only do one or the other (in this case, only make a call to a function & do all work there)

  5. when creating ID values, stick to the same standards used when creating variable names (don’t call them 1, 2, 3, etc)

Here’s my *.TS file

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
    selector: 'page-home',
    templateUrl: 'home.html'
})
export class HomePage {

    public _fish:any[];
    public _bears:any[];

    constructor(public navCtrl: NavController) {
        this._fish = [
                    {
                        'species' : 'Rainbow Trout',
                        'imageSrc':'../assets/images/fish/rainbow.png',
                        'currentValue' : true
                    },
                    {
                        'species' : 'Brown Trout',
                        'imageSrc':'../assets/images/fish/brown.png',
                        'currentValue' : false
                    }
        ];

        this._bears = [
                    {
                        'species' : 'Polar',
                        'imageSrc':'../assets/images/bears/polar.png',
                        'currentValue' : true
                    },
                    {
                        'species' : 'Black',
                        'imageSrc':'../assets/images/bears/black.png',
                        'currentValue' : false
                    }
        ];
    }

    CheckboxClicked(item: any, $event) {
        console.log('CheckboxClicked for ' + item.species);
    }

    ParentElementClicked(zoneName: string) {
        console.log('ParentElementClicked for ' + zoneName);
    }
}

And my *.HTML file

<ion-header>
    <ion-navbar>
        <ion-title>Home</ion-title>
    </ion-navbar>
</ion-header>

<ion-content padding>

    <ion-card (click)="ParentElementClicked('fishZone')">
        <ion-card-header>
            Fish
        </ion-card-header>
        <ion-card-content>
                <ion-item *ngFor="let fish of _fish; let i = index">
                    <ion-label> {{ fish.species }} </ion-label>
                    <ion-checkbox [checked]="fish.currentValue" (click)="CheckboxClicked(fish, $event)"></ion-checkbox>
                </ion-item>
        </ion-card-content>
    </ion-card>

    <ion-card (click)="ParentElementClicked('bearZone')">
        <ion-card-header>
            Bears
        </ion-card-header>
        <ion-card-content>
                <ion-item *ngFor="let bear of _bears; let i = index">
                    <ion-label> {{ bear.species }} </ion-label>
                    <ion-checkbox [checked]="bear.currentValue" (click)="CheckboxClicked(bear, $event)"></ion-checkbox>
                </ion-item>
        </ion-card-content>
    </ion-card>

</ion-content>

Good luck,
Ryan


#3

Leading underscores are conventionally reserved for private properties, not public. This is also abuse of any; create an interface.


#6

@Smirnova, if you have any questions with my code, let me know. I’m not certain if my 2 separate objects (fish and bears) replicate the issue you’re having with your sample items.

Thanks,
Ryan


#8

Oh, that’s lot of things to consider! Thanks a lot for your detailed answer.


#9

Hmm, good point, I didn’t know about underscore convention for private vars. Yep, in my real code I’m using interface. Thanks hips!


#11

The advice about not using any, ever, is probably the single most helpful piece of advice I’ve received on this forum. I was kindof abusing it. It saves you a ridiculous amount of time in the long run. It’s just a pain for a hot minute.