# AUR9989

## Error Message

`AUR9989: Invalid query selector. Only selectors with alpha-numeric characters, or $all are allowed. Got <selector> instead.`

Where `<selector>` is the invalid query string provided.

## Description

This error occurs when the query selector string provided to the `@children` decorator or its options does not meet the validation criteria enforced by Aurelia.

## Cause

The `@children` decorator uses a simplified query mechanism compared to standard `document.querySelectorAll`. Based on the implementation in `packages/runtime-html/src/templating/children.ts`, the query selector string must conform to one of the following:

1. **The special value `$all`:** This selects all direct child elements.
2. **A selector matching the pattern `/^(?:[$a-z](?:[$a-z0-9]*))(?:\.(?:[$a-z0-9]+))+$/i`:**
   * Starts with a letter (`a-z`, case-insensitive) or a dollar sign (`$`).
   * Followed by zero or more letters, numbers, or dollar signs. (This part seems intended to match element tag names, potentially including custom elements).
   * Followed by *one or more* class selectors (e.g., `.class1`, `.class2`). Each class name must consist only of letters and numbers (`a-z`, `0-9`, case-insensitive).

This means the following are **not** allowed:

* Selectors with spaces (e.g., `div .item`)
* ID selectors (e.g., `#my-id`)
* Attribute selectors (e.g., `[data-value="foo"]`)
* Pseudo-classes or pseudo-elements (e.g., `:first-child`, `::before`)
* Combinators (e.g., `div > span`, `h2 + p`)
* Complex type selectors beyond the initial simple one (e.g., `div.container span`)
* Selectors without at least one class name (unless it's `$all`).

The error message simplifies this, stating only "alpha-numeric characters or $all" are allowed, but the underlying check is slightly more specific as described above.

## Solution

Modify the query selector provided to `@children` to conform to the allowed patterns:

1. Use `$all` to select all direct child elements.
2. Use a simple selector consisting of an optional element name followed by one or more class names composed only of letters and numbers (e.g., `div.item`, `.product-card`, `my-element.active.highlight`).

If you need more complex selection logic, query the elements manually within the component's lifecycle hooks (e.g., `attached`) using standard DOM methods like `this.$host.querySelectorAll()` and filter the results as needed.

## Example

```typescript
import { customElement, children, ILifecycleHooks, LifecycleHooks } from 'aurelia';

// Assume $all is imported or defined if used directly
const $all = '$all';

@customElement({ /* ... */ })
@LifecycleHooks() // Needed for manual query in attached
export class MyListComponent implements ILifecycleHooks {

  // Correct: Select all children
  @children({ query: $all })
  allChildren: Element[];

  // Correct: Select children matching 'list-item.active'
  @children({ query: 'list-item.active' })
  activeItems: Element[];

  // Correct: Select children with class '.highlight' (element tag implicitly *)
  @children('.highlight')
  highlightedItems: Element[];

  // Incorrect: Contains space/combinator
  // @children('div .item')
  // invalidItems1: Element[];

  // Incorrect: Contains ID selector
  // @children('#main-item')
  // invalidItems2: Element[];

  // Incorrect: Contains attribute selector
  // @children('[data-id]')
  // invalidItems3: Element[];

  // Incorrect: Contains pseudo-class
  // @children(':nth-child(odd)')
  // invalidItems4: Element[];

  // Incorrect: No class name provided (and not $all)
  // @children('button')
  // invalidItems5: Element[];

  complexItems: Element[] = [];

  constructor(private readonly $host: HTMLElement) {}

  // Solution for complex queries: Manual query
  attached() {
    this.complexItems = Array.from(this.$host.querySelectorAll('div > .item[data-value="special"]:not(.disabled)'));
    console.log('Found complex items:', this.complexItems);
  }
}
```

## Debugging Tips

* Carefully examine the selector string passed to `@children`.
* Remove any characters or syntax elements other than letters, numbers, dots (`.`) for classes, and the initial optional `$`.
* Ensure the selector includes at least one class name if it's not `$all`.
* Test the selector against the regex `/^(?:[$a-z](?:[$a-z0-9]*))(?:\.(?:[$a-z0-9]+))+$/i` or simplify it to meet the requirements.
* If complex selection is necessary, switch to manual querying using `this.$host.querySelectorAll()` in appropriate lifecycle hooks.


---

# 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/aur9989.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.
