Cancel an ionChange event?


#1

I have a situation where I have a number of checkboxes created in an *ngFor loop. Say there’s 5… I want to limit selections to, say, 3. Can I disallow the 4th selection by some logic in the ionChange method I’ve tied to the checkbox? I’ve tried setting event.value to false and returning false from the event, but those ideas didn’t pan out.

My end goal is to keep the user from selecting only X items of Y choices by canceling the event in the event handler, and posting a message that they have already selected the max number of possible choices and forcing them to deselect something to select another choice.

Is there a simpler way? Maybe by setting up a group of some sort and doing this natively somehow?

Thanks in advance for any ideas.

Regards,

Bret


#2

You can’t disable lines in the checkbox, but you can disable a submit button, and put an error message next to it, like “select at most three”.

If you’re repeating this in an ngFor, I think the cleanest way is to create a component that extends ion-checkbox. schuhma-checkbox. The component emits the choices when the user clicks submit, and handles the error message inside itself, so your main page html looks very simple.


#3

Thanks, Aaron, I appreciate your thoughts and time to respond. You’ve given me several ideas to think about.

That’s not quite the UI experience I’m going for… I want more direct, immediate feedback that the user’s choices have violated the rules… it’s a voting application and it must be VERY clear to users that they are trying to OVER vote and they must take some action (deselect a selection) to vote for another candidate; I can’t let them overvote and leave it up to the user to figure out why the “next” button isn’t available, even with onscreen information explaining why. I’ll keep working at this with your suggestions in mind, though :slight_smile: .

Regards,

Bret


#4

I’ve done more work on this and neither ionChange, nor click events are much help. In fact I’m using them BOTH and I cannot cause the checkbox to keep from changing states.

HTML:
<ion-checkbox (ionChange)="item.ionChangeUpdateCheckbox($event)" (click)="item.updateCheckbox($event)"></ion-checkbox>

TS file:
Nothing in THIS method should cause the checkbox to change behavior… this just sets some messages

    ionChangeUpdateCheckbox(event) {
        if (event.checked) {
            this.currentlySelected += 1;
        } else {
            this.currentlySelected -= 1;
        }

        if (this.currentlySelected == this.votesAllowed) {
            this.statusMessage = "You have selected the maximum number of candidates for this race."
        } else if (this.votesAllowed > this.currentlySelected) {
            this.statusMessage = "You can select " + (this.votesAllowed - this.currentlySelected)
                + " more candidate(s)."
        } else {
            this.statusMessage = "You have selected too many candidates - please deselect "
                + (this.currentlySelected - this.votesAllowed) + " candidate(s)."
        }
    }

SEVERAL of these event.* methods should keep the event from bubbling and/or doing the default thing - NONE of them work

    updateCheckbox(event: Event): boolean {
        if (this.canSelectMoreCandidates()) {
            event.preventDefault();
            event.stopImmediatePropagation();
            event.cancelBubble = true;
            event.stopPropagation();
            return (false);
        }
        return (true);
    }

Is the checkbox busted? Why does ionChange provide a different type of Event object than the standard JS DOM Event you get in a “click” event?

I want more of the behavior I get with click (which provides a JS DOM Event and access to stopPropagation() and preventDefault(), if they worked), but I need the ability to work with the event.clicked, which you only get with the ionChange Event object. (the “clicked” element isn’t available in the event object you get in the JS DOM Event, which is weird be cause I pass the SAME object to each). Ideally I’d only have ionChange but get access to a working form of preventDefault() or stopPropagation().

Please check this site out for what I’m going for: http://anywhereballot.com/race/president-and-vice-president-of-the-united-states/ . Try selecting a second choice when the page loads and you’ll see what I mean. The checkboxes aren’t made unavailable when you hit the max selections - when you select more than the max a modal popup appears and tells you to deselect a choice, then select something else.

Thanks for your insights!

Regards,

Bret


#5

“Simpler” is in the eye of the beholder, but this works:

export class HomePage {
  fruits = ['apple', 'banana', 'cherry'];
  basket = [false, false, false];
  selcount = 0;
  maxcount = 2;

  onFruitSelectionChange(fix: number, cbox: Checkbox): void {
    if (cbox.checked != this.basket[fix]) {
      if (cbox.checked) {
        if (this.selcount >= this.maxcount) {
          alert("basket is full");
          cbox.checked = false;
          return;
        }
        this.basket[fix] = true;
        ++this.selcount;
      } else {
        this.basket[fix] = false;
        --this.selcount;
      }
    }
  }
}
<ion-list>
  <ion-item *ngFor="let fruit of fruits; let fix = index">
    <ion-label>{{fruit}}</ion-label>
    <ion-checkbox [checked]="basket[fix]" (ionChange)="onFruitSelectionChange(fix, $event)"></ion-checkbox>
  </ion-item>
</ion-list>

How do I prevent an ion-checkbox from being checked?
#6

In v3, ionChange is an Angular EventEmitter, which emits a BaseInput (an internal class that pretty much every input-type component extends). You can think of it giving you a snapshot of the current state of the component. So it give you more information than just the current click.

In v4, ionChange will be much closer to what you might be expecting. It is a Stencil-based EventEmitter (not Angular), and it basically emits a string with an event code.


#7

OMG, Robert! This was so simple! I had no idea you could cast $event to a Checkbox! I figured since I passed $event I had to deal with it as an Ionic Event object. The real key was both being able to retrieve the state via cbox.checked and setting it (I kept trying cbox.checked(false)). I didn’t even need the “fix” index.

Thanks Robert!!

Regards,

Bret


#8

This works because the event is a collection of core features of a checkbox (i.e., a BaseInput). There’s no official documentation about what I’m going to say now, so things might change, but my read of the v4 source code for ionChange itells me that the code @rapropos gave you will break in v4. I don’t know a better way to solve the problem though, just be aware that change is coming.


#9

Thanks, Aaron - and thanks for the V3 vs V4 info you provided above, too :slight_smile: . I’ll have to keep my eyes open and rework this part if/when things change. I appreciate your input! :slight_smile:

Regards,

Bret