# 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:

1. **Method Decorator:** To automatically call the decorated method when a specified expression changes.

   ```typescript
   class MyClass {
     @watch('expression')
     myHandlerMethod() { /* ... */ }
   }
   ```
2. **Class Decorator:** To specify watchers via a configuration object.

   ```typescript
   @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:**

  ```typescript
  class MyClass {
    @watch('someExpression') // Incorrect: Applied to a property
    myProperty: string = 'value';
  }
  ```
* **Getters/Setters:**

  ```typescript
   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:

1. **A standard class method:** when you want that method to be the change handler.
2. **The class definition itself:** when you are providing a configuration object with `expression` and `changeHandler` 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

```typescript
import { watch, resolve } from '@aurelia/runtime-html';
import { ILogger } from '@aurelia/kernel';

export class MyViewModel {
  private readonly logger = resolve(ILogger);
  firstName: string = 'John';
  lastName: string = 'Doe';
  userId: number = 1;

  // 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 {
   private readonly logger = resolve(ILogger);
   userId: number = 10;

   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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aurelia.io/developer-guides/error-messages/runtime-html/aur0774.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
