AUR0774
Error Message
AUR0774: Invalid @watch decorator usage: decorated target <targetName> is not a class method.
Where <targetName>
is the name of the property or field that was incorrectly decorated.
Description
This error occurs when the @watch
decorator is applied to something other than its intended targets: a class method (when used as a method decorator) or a class definition (when used as a class decorator with a configuration object).
Cause
The @watch
decorator is designed for specific use cases:
Method Decorator: To automatically call the decorated method when a specified expression changes.
class MyClass { @watch('expression') myHandlerMethod() { /* ... */ } }
Class Decorator: To specify watchers via a configuration object.
@watch({ expression: 'expr', changeHandler: 'handlerMethodName' }) class MyClass { handlerMethodName() { /* ... */ } }
This error (AUR0774) occurs if you try to apply @watch
to other kinds of class members, such as:
Class Fields/Properties:
class MyClass { @watch('someExpression') // Incorrect: Applied to a property myProperty: string = 'value'; }
Getters/Setters:
class MyClass { _value: string; @watch('someExpression') // Incorrect: Applied to a getter get myValue() { return this._value; } }
The decorator logic specifically checks if context.kind
(from decorator metadata) is 'method'
or 'class'
depending on how it's invoked. If it's anything else (like 'field'
, 'getter'
, 'setter'
, etc.), this error is thrown.
Solution
Ensure that the @watch
decorator is only applied to:
A standard class method: when you want that method to be the change handler.
The class definition itself: when you are providing a configuration object with
expression
andchangeHandler
properties.
Do not apply @watch
to class fields (properties), getters, or setters. If you need to react to changes related to these, watch the underlying properties or use other appropriate patterns.
Example
import { watch } from '@aurelia/runtime-html';
import { ILogger } from '@aurelia/kernel';
export class MyViewModel {
firstName: string = 'John';
lastName: string = 'Doe';
userId: number = 1;
constructor(@ILogger private readonly logger: ILogger) {}
// Correct: @watch applied to a method
@watch('firstName')
firstNameChanged(newValue: string, oldValue: string) {
this.logger.info(`First name changed: ${oldValue} -> ${newValue}`);
}
// Correct: @watch applied to the class
@watch({ expression: 'lastName', changeHandler: 'lastNameChangedHandler' })
static { /* Class decorator usage */ }
lastNameChangedHandler(newValue: string, oldValue: string) {
this.logger.info(`Last name changed: ${oldValue} -> ${newValue}`);
}
// Incorrect: @watch applied to a property/field - Causes AUR0774
// @watch('userId')
// watchedUserId: number = this.userId;
private _internalValue: string = 'initial';
// Incorrect: @watch applied to a getter - Causes AUR0774
// @watch('somethingElse')
// get computedValue(): string {
// return this._internalValue.toUpperCase();
// }
// Incorrect: @watch applied to a setter - Causes AUR0774
// @watch('yetAnotherThing')
// set computedValue(value: string) {
// this._internalValue = value;
// }
}
// Correct class decorator usage syntax
@watch({ expression: 'userId', changeHandler: 'userIdChangedHandler' })
export class UserComponent {
userId: number = 10;
constructor(@ILogger private readonly logger: ILogger) {}
userIdChangedHandler(newValue: number, oldValue: number){
this.logger.info(`User ID changed: ${oldValue} -> ${newValue}`);
}
}
Debugging Tips
Locate the
@watch
decorator mentioned in the stack trace.Verify what kind of class member it is attached to (method, field, getter, setter, class).
Move the
@watch
decorator to the appropriate handler method or use it as a class decorator with the correct configuration object if necessary.
Last updated
Was this helpful?