Home > Back-end >  Vue (Class syntax) - TypeError: handler.apply is not a function
Vue (Class syntax) - TypeError: handler.apply is not a function

Time:02-06

I'm using Vue 2 (class syntax) and Typescript (TSX syntax) -- but if you aren't familiar with TSX in Vue, answer in regular ts/js syntax and I'll apply it to TSX as long as it's also Vue's class syntax -- and I know this question has been asked a few times but none of the answers I've seen have applied to my own situation.

I've created an object array where each object has a name and a boolean. I'm outputting these objects as the company I work for's custom HTML elements, let's call them ZChips (basically act like pretty but dumb radio selects). A ZChip takes the property 'selected' as a boolean on, you guessed it, whether or not it's selected.

The array is called registerCategory and each object in the array has a name (basically just its text) and a boolean i called is_selected whose default is false.

Alright, here's how I've outputted my Array (reminder this is TSX syntax and output works fine)

  {this.registerCategory.map((field, index) => (
    <ZChip
    position={'start'}
    id = {'field-'   index}
    value={field}
    selected={this.registerCategory[index].is_selected}
    onClick={this.onCategorySelect(index)}
    >
      {this.$t(this.registerCategory[index].name)}
    </ZChip>
  ))}

This outputs all the elements wonderfully. My issue now is getting them to be selected on click.

I've made this function in a separate registration.mixin.ts file (which is also the same place the array is defined in a computed block):

  methods: {
    onCategorySelect(index: number): void {
      this.registerCategory[index].is_selected = true;
    },
}

This should change the is_select as only the selected element's selected boolean. However, that gave me:

[Vue warn]: Invalid handler for event "click": got undefined

When I change void in onCategorySelect to boolean and instead return the result, the undefined warning goes away but instead gives me:

[Vue warn]: Error in v-on handler: "TypeError: handler.apply is not a function"

This is apparently because I've changed the value directly. I've tried multiple different ways though (i.e. defined my own in-block boolean and assigned is_selected to that, etc. but everything I've tried either gives me the same errors or just returns an infinite loop).

And if you're wondering if the Array is at fault -- the same issue occurs when I tried putting them out as separate elements.

I've also tried a simple toggle solution (defining a boolean, toggling its value on click) but that obviously returns ALL the elements as selected once toggled. I know there's a way to bypass that in Vue, I'm just too new it to figure it out.

Any help, solution, or work-around is greatly appreciated. Thanks. :)

CodePudding user response:

Did you figure it out already? I can't test it, but I am pretty sure this works, it matches how indexes are handled in React (afaik):

  methods: {
    onCategorySelect(index: number): void {
      () => this.registerCategory[index].is_selected = true;
    },
  }

CodePudding user response:

Answering my question in depth in case anyone needs it -- with the help of my supervisor, I've figured out that 2 things were a problem in my code:

  1. I've dumbly put the array in computed object (because -- correct me if I'm wrong -- as far as I know Arrays with custom types can't be defined in the data object, and anything in a computed block can't be mutated. So I moved the array to the same class the rest of my code was (where the ZChip elements are). I'm sure there is some better place to put the Array initialization other than where I put it but oh well.

  2. In onClick, I had to use arrow function expression to call the function. This is how the code's been changed:

      {this.registerCategory.map((field, index) => (
        <ZidChip
        position="start"
        id = {'field-'   index}
        value={field}
        selected={this.registerCategory[index].is_selected}
        onClick={() => this.onCategorySelect(index)}
        >
          {this.$t(this.registerCategory[index].name)}
        </ZidChip>
      ))}
    

Where onCategorySelect looks like:

  private onCategorySelect(index: number): void {
    this.registerCategory[index].is_selected = !this.registerCategory[index].is_selected;
  }
  • Related