AUR0773

Error Message

AUR0773: Invalid @watch decorator change handler config. Method "<methodName>" not found in class <ClassName>

Where <methodName> is the name provided as the change handler, and <ClassName> is the name of the class where @watch was used.

Description

This error occurs when using the @watch decorator as a class decorator with a configuration object, and the changeHandler property in that configuration is a string, but there is no method with that specified name on the decorated class.

The @watch decorator needs a valid function (either provided directly or found by name on the class) to call when the watched expression changes.

Cause

This error specifically happens under these conditions:

  1. @watch is used as a class decorator: @watch({...})(MyClass) or @watch({...}) class MyClass { ... }

  2. A configuration object is passed to @watch.

  3. The configuration object has a changeHandler property that is a string (e.g., { changeHandler: 'myMethodName' }).

  4. The class (MyClass in the example) does not have a method named myMethodName.

import { watch } from '@aurelia/runtime-html';

// Incorrect: 'valueChangedHandler' method does not exist on the class
@watch({
  expression: 'value',
  changeHandler: 'valueChangedHandler' // Typo or missing method
})
export class MyViewModel {
  value: string = 'test';

  // Missing the required 'valueChangedHandler' method
  // valueChangedHandler(newValue, oldValue) { /* ... */ }
}

// Incorrect: changeHandler name mismatch
@watch({
  expression: 'count',
  changeHandler: 'handleCountChange'
})
export class Counter {
  count: number = 0;

  // Method exists, but name doesn't match the changeHandler string
  countChanged(newValue, oldValue) {
    console.log(newValue, oldValue);
  }
}

Solution

  1. Verify Method Name: Ensure the string provided in the changeHandler property exactly matches the name of an existing method on the decorated class. Check for typos.

  2. Implement the Method: If the method is missing, implement it on the class with the correct name.

  3. Use Method Decorator: Alternatively, apply @watch directly to the handler method itself instead of using it as a class decorator with a string changeHandler. This is often simpler and less prone to typos.

Example

import { watch } from '@aurelia/runtime-html';
import { ILogger } from '@aurelia/kernel';

// Correct: Using @watch as a class decorator with a valid string changeHandler
@watch({
  expression: 'value',
  changeHandler: 'valueChangedHandler' // Matches the method name below
})
export class MyViewModel {
  value: string = 'test';

  constructor(@ILogger private readonly logger: ILogger) {}

  // The method exists with the correct name
  valueChangedHandler(newValue: string, oldValue: string) {
    this.logger.info(`Value changed via class decorator: ${oldValue} -> ${newValue}`);
  }
}

// Correct: Using @watch as a method decorator (often preferred)
export class AnotherViewModel {
  count: number = 0;

  constructor(@ILogger private readonly logger: ILogger) {}

  // Apply @watch directly to the handler method
  @watch('count')
  handleCountChange(newValue: number, oldValue: number) {
    this.logger.info(`Count changed via method decorator: ${oldValue} -> ${newValue}`);
  }
}


// Incorrect setup causing AUR0773:
// @watch({
//   expression: 'data',
//   changeHandler: 'dataHandler' // No method named 'dataHandler' exists
// })
// export class BrokenViewModel {
//   data: any = null;
//   dataChanged(newValue, oldValue) { /* Handler exists, but wrong name */ }
// }

Debugging Tips

  • Carefully compare the string value of the changeHandler property in the @watch configuration object with the method names defined in your class.

  • Check for subtle differences like capitalization or spelling errors.

  • Consider refactoring to use @watch as a method decorator on the handler function, which eliminates the need for the string name lookup.

Last updated

Was this helpful?