# AUR9998

## Error Message

`AUR9998: Spread binding does not support spreading custom attributes/template controllers. Did you build the spread instruction manually?`

## Description

This error occurs when the Aurelia template compiler encounters an attempt to use spread binding syntax (`...`) with template controllers (like `if`, `repeat`, `switch`) or custom attributes that are not meant to be spread. The spread binding feature in Aurelia is designed specifically for spreading bindable properties onto custom elements, not for template controllers or certain types of custom attributes.

## Cause

This error typically happens when:

1. **Spreading Template Controllers**: Attempting to spread template controllers like `if`, `repeat`, `switch`, etc.
2. **Spreading Non-Bindable Attributes**: Trying to spread custom attributes that don't support being spread
3. **Manual Instruction Building**: Manually constructing spread instructions in a way that's not supported by the template compiler
4. **Invalid Spread Syntax**: Using spread syntax in contexts where it's not allowed

## Common Scenarios

### ❌ Incorrect: Spreading Template Controllers

```html
<!-- This will throw AUR9998 -->
<template>
  <div ...="templateControllerProps"></div>
</template>
```

```typescript
export class MyComponent {
  templateControllerProps = {
    'if.bind': 'showElement',
    'repeat.for': 'item of items'
  };
}
```

### ❌ Incorrect: Spreading Custom Attributes

```html
<!-- This might throw AUR9998 depending on the attribute -->
<template>
  <div ...="customAttributeProps"></div>
</template>
```

```typescript
export class MyComponent {
  customAttributeProps = {
    'my-custom-attribute.bind': 'someValue'
  };
}
```

## Solution

### 1. **Use Spread Only for Bindable Properties**

Spread binding should only be used to spread bindable properties of custom elements:

```html
<!-- ✅ Correct: Spreading bindables onto a custom element -->
<template>
  <my-custom-element ...="elementProps"></my-custom-element>
</template>
```

```typescript
export class MyComponent {
  elementProps = {
    'title.bind': 'pageTitle',
    'visible.bind': 'isVisible',
    'data.bind': 'componentData'
  };
}
```

### 2. **Use Template Controllers Directly**

Instead of trying to spread template controllers, use them directly:

```html
<!-- ✅ Correct: Use template controllers directly -->
<template>
  <div if.bind="showElement">Content shown conditionally</div>
  <div repeat.for="item of items">${item.name}</div>
</template>
```

### 3. **Use Individual Bindings for Custom Attributes**

For custom attributes, bind them individually rather than spreading:

```html
<!-- ✅ Correct: Individual custom attribute bindings -->
<template>
  <div my-custom-attribute.bind="someValue"
       another-attribute.bind="anotherValue">
    Content
  </div>
</template>
```

### 4. **Check Your Custom Element Definition**

Ensure your custom element properly defines bindable properties:

```typescript
import { bindable, customElement } from '@aurelia/runtime-html';

@customElement({
  name: 'my-custom-element',
  template: '<div>${title}</div>'
})
export class MyCustomElement {
  @bindable title: string;
  @bindable visible: boolean;
  @bindable data: unknown;
}
```

## Example: Correct Usage

```html
<!-- my-app.html -->
<template>
  <!-- ✅ Correct: Spreading bindables to custom elements -->
  <user-card ...="userProps"></user-card>
  
  <!-- ✅ Correct: Template controllers used directly -->
  <div if.bind="showUserList">
    <user-card repeat.for="user of users" ...="user"></user-card>
  </div>
</template>
```

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

@customElement({
  name: 'my-app',
  template: '...' // template from above
})
export class MyApp {
  users = [
    { name: 'John', email: 'john@example.com', active: true },
    { name: 'Jane', email: 'jane@example.com', active: false }
  ];

  userProps = {
    'name.bind': 'currentUser.name',
    'email.bind': 'currentUser.email',
    'active.bind': 'currentUser.active'
  };

  showUserList = true;
  currentUser = this.users[0];
}
```

## Debugging Tips

1. **Check Spread Target**: Ensure you're only spreading onto custom elements, not regular HTML elements or template controllers
2. **Verify Bindable Properties**: Make sure all properties in your spread object correspond to actual `@bindable` properties on the target custom element
3. **Review Template Structure**: Look for any template controllers (`if`, `repeat`, `switch`) that might be accidentally included in spread objects
4. **Check Manual Instructions**: If you're manually building template instructions, ensure you're not creating spread instructions for unsupported scenarios

## Related

* See [Bindable Properties documentation](https://docs.aurelia.io/components/bindable-properties) for more information on defining bindable properties
* See [Template Controllers documentation](https://docs.aurelia.io/getting-to-know-aurelia/composition-patterns/template-controllers) for proper usage of `if`, `repeat`, and other template controllers
