# AUR0772

## Error Message

`AUR0772: Invalid @watch decorator config. Expected an expression or a fn but received null/undefined.`

## Description

This error occurs when using the `@watch` decorator, but the required first argument (the expression to watch) is `null` or `undefined`. The `@watch` decorator needs a valid target to observe for changes.

## Cause

The primary cause is providing `null` or `undefined` as the first argument to the `@watch` decorator.

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

export class MyViewModel {
  // Incorrect: Passing null as the expression
  @watch(null)
  nullWatchHandler() { /* ... */ }

  // Incorrect: Passing undefined as the expression
  @watch(undefined)
  undefinedWatchHandler() { /* ... */ }

  // Incorrect: Passing a variable that is null/undefined
  @watch(someVariableThatMightBeNull)
  variableWatchHandler() { /* ... */ }
}
```

## Solution

Ensure that the first argument provided to the `@watch` decorator is always a valid string representing the property path or expression to watch, or a function that selects the value to watch.

1. **Provide a Valid Expression:** Replace `null` or `undefined` with a string expression (e.g., `'myProperty'`, `'user.address.street'`) or a function.
2. **Check Variables:** If using a variable for the expression, ensure it holds a valid string or function before being used in the decorator. Decorator arguments are evaluated at class definition time.

## Example

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

export class MyViewModel {
  private readonly logger = resolve(ILogger);
  firstName: string = 'John';
  lastName: string = 'Doe';
  address: { street: string, city: string } = { street: '123 Main St', city: 'Anytown' };

  // Correct: Watching a simple property using a string
  @watch('firstName')
  firstNameChanged(newValue: string, oldValue: string) {
    this.logger.info(`First name changed from ${oldValue} to ${newValue}`);
  }

  // Correct: Watching a nested property using a string path
  @watch('address.street')
  streetChanged(newValue: string, oldValue: string) {
    this.logger.info(`Street changed from ${oldValue} to ${newValue}`);
  }

  // Correct: Watching an expression using a function
  @watch((vm: MyViewModel) => vm.firstName + ' ' + vm.lastName)
  fullNameChanged(newValue: string, oldValue: string) {
    this.logger.info(`Full name changed from ${oldValue} to ${newValue}`);
  }

  // Correct: Watching multiple properties via a function returning an array
  @watch((vm: MyViewModel) => [vm.address.street, vm.address.city])
  addressChanged(newValues: [string, string], oldValues: [string, string]) {
    this.logger.info(`Address parts changed from ${oldValues?.join(', ')} to ${newValues.join(', ')}`);
  }

  // Incorrect examples that would cause AUR0772:
  // @watch(null)
  // invalidNullHandler() { /* ... */ }

  // @watch(undefined)
  // invalidUndefinedHandler() { /* ... */ }
}

```

## Debugging Tips

* Verify the arguments passed to the `@watch` decorator directly in your component's code.
* Ensure any variables used as arguments to `@watch` are defined and have the correct type (string or function) at the time the class is defined. Remember that decorator code runs early in the class definition process.

```
```
