11

I have a list of items coming in from an API and they won't always be the same, so the number of items in the array is always changing. I'm creating a checkbox for each item.

The user has the ability to check/uncheck each item. Here's what I want to do:

  1. When an item is checked, it will push the ID of that item into an array
  2. When an item is unchecked, it will remove the ID of that item from the array

I just need to know how I call something based on whether it was checked or unchecked. I've tried a "checked.delegate" and a "checked.trigger" and I can't seem to get that to work.

Just a regular click.delegate won't work because I can't keep state on whether it's true or false and I can't set variables for all of them because I don't always know which items are going to be coming in from the API. Any suggestions?

Brandon
  • 3,074
  • 3
  • 27
  • 44

3 Answers3

26

Try change.delegate or change.trigger like this:

VM method:

logchange(value) {
  console.log(value);
}

View:

<input type="checkbox" change.delegate="logchange($event.target.checked)" />
Ashley Grant
  • 10,879
  • 24
  • 36
  • I don't think this will work because I need to call 1 method when it's checked and 1 method when it's unchecked. How would I access whether they are checking or unchecking? – Brandon Jul 08 '16 at 15:32
0

There is (since when?) official documentation of how to solve exactly this specific problem cleanly: https://aurelia.io/docs/binding/checkboxes#array-of-numbers

No need to handle events!
Aurelia can bind directly to your array and handle everything for you - all you need to do is tell Aurelia what property of the elements you are repeating over to store in the array (the id).

The gist of it:

app.js

  export class App {
    products = [
      { id: 0, name: 'Motherboard' },
      { id: 1, name: 'CPU' },
      { id: 2, name: 'Memory' },
    ];
  
    selectedProductIds = [];
  }

app.html

  <template>
    <form>
      <h4>Products</h4>
      <label repeat.for="product of products">
        <input type="checkbox" model.bind="product.id" checked.bind="selectedProductIds">
        ${product.id} - ${product.name}
      </label>
      <br>
      Selected product IDs: ${selectedProductIds}
    </form>
  </template>

No other code is needed.

AnorZaken
  • 1,916
  • 1
  • 22
  • 34
-1

One way you can do this is with the help of a setter. Let's say you have a checkbox like this:

<input type="checkbox">

Create a private field in your View Model and then wrap it with a getter and a setter:

get isChecked(){
    return this._isChecked;
}

set isChecked(value){
    this._isChecked = value;
    //enter your extra logic here, no need for an event handler
}

private _isChecked: boolean;

Then bind isChecked to the view:

<input type="checkbox" checked.bind="isChecked">

Every time the checkbox is checked or unchecked the setter will be called and you can call any method you want from within the setter.

Another more unconventional way to achieve this is by using the @bindable decorator like this:

@bindable isChecked: boolean;

It's unconventional because you probably don't want isChecked to be bindable but the decorator gives you access to the isCheckedChanged method:

isCheckedChanged(newValue, oldValue){
     //Logic here
}

And of course there is the change event which you can catch with change.trigger and change.delegate but that has already been mentioned in another answer

dimlucas
  • 5,040
  • 7
  • 37
  • 54
  • Creating getters/setters like you are doing here is most definitely the wrong way to do this in Aurelia. Using getter/setters will cause Aurelia's binding engine to switch to using dirty checking. If you are doing this in your own Aurelia applications, I implore you to stop doing this. – Ashley Grant Jul 08 '16 at 13:50
  • 1
    But more importantly, this answer wouldn't work for OP's specific question. OP is working inside a repeater, and thus will have an arbitrary number of checkboxes to work with. – Ashley Grant Jul 08 '16 at 13:55