# Scope and context

Ever wondered how Aurelia knows where to find your data when you write `${message}` in a template? Or why `$parent.something` works like magic in nested components? Welcome to the world of **scope** and **binding context** – the invisible machinery that makes Aurelia's data binding so delightfully intuitive.

Think of scope as Aurelia's GPS system for finding your data. Just like GPS needs to know your current location to give you directions, Aurelia's binding expressions need to know their current context to find the right data.

{% hint style="success" %}
**What you'll learn in this guide:**

* How scope and binding context work under the hood
* The difference between binding context and override context (and why you should care)
* How to navigate between parent and child scopes like a pro
* When and why component boundaries matter
* The magic behind `$parent`, `$host`, and other special keywords
* How to debug those tricky scope-related issues
  {% endhint %}

## The Big Picture: What is Scope?

Before diving into the details, let's start with a simple analogy. Imagine you're at a family reunion, and someone shouts "Hey, John!" Three different people named John might turn around. To know which John they meant, you need **context** – are they talking to Uncle John, Cousin John, or Little Johnny?

Aurelia faces the same challenge. When it sees `${name}` in your template, it needs to know:

* Which object contains the `name` property?
* Should it look in the current component's data?
* What about parent components?
* Are there any special contextual values (like `$index` from a `repeat.for`)?

This is where **scope** comes in. A scope is like a GPS coordinate that tells Aurelia exactly where to look for data.

### The JavaScript Analogy

If you're familiar with JavaScript's function binding, you'll find this concept familiar:

```typescript
function greet() {
  return `Hello, ${this.name}!`;
}

const person1 = { name: 'Alice' };
const person2 = { name: 'Bob' };

console.log(greet.call(person1)); // "Hello, Alice!"
console.log(greet.call(person2)); // "Hello, Bob!"
```

Just like JavaScript's `this` binding, Aurelia expressions need a context object to work with. The difference is that Aurelia's scope system is more sophisticated – it can look through multiple layers of context to find what it needs.

## Anatomy of a Scope

Every scope in Aurelia has three main parts:

```
┌─────────────────────────┐
│       Scope             │
│                         │
│  ┌─────────────────┐    │
│  │ bindingContext  │    │ ← Your component's data
│  └─────────────────┘    │
│                         │
│  ┌─────────────────┐    │
│  │ overrideContext │    │ ← Special contextual values
│  └─────────────────┘    │
│                         │
│  parent ────────────────┼─→ Points to parent scope
│  isBoundary: boolean    │ ← Component boundary marker
└─────────────────────────┘
```

### 1. Binding Context: Your Data Home

The **binding context** is usually your component's instance – the object containing all your properties and methods:

```typescript
export class MyComponent {
  message = 'Hello, World!';
  count = 42;

  greet() {
    return `The count is ${this.count}`;
  }
}
```

When Aurelia evaluates `${message}` in the template, it looks at the binding context (your component instance) and finds the `message` property.

### 2. Override Context: Special Contextual Values

The **override context** holds special values that aren't part of your component but are available in templates. The most common example is loop variables:

```html
<div repeat.for="item of items">
  ${$index}: ${item.name}  <!-- $index comes from override context -->
</div>
```

In this example:

* `item` is added to a child scope's binding context
* `$index`, `$first`, `$last`, etc. are added to the override context

### 3. Scope Hierarchy and Parent Access

Scopes form a hierarchy. Each component creates its own scope, and child components can access parent data using `$parent`:

```html
<!-- parent-component.html -->
<div>
  <child-component></child-component>
</div>

<!-- child-component.html -->
<p>Parent's title: ${$parent.title}</p>
```

### 4. Component Boundaries

Component boundaries are important to understand. When you create a custom element, Aurelia marks that scope as a **boundary**. This affects how property resolution works:

* Within a component, Aurelia searches up the scope chain automatically
* At component boundaries, you must use `$parent` explicitly to access parent component data

```html
<!-- This works within the same component -->
<div with.bind="user">
  ${name}  <!-- Finds user.name, then falls back to component properties -->
</div>

<!-- To access parent component data, use $parent -->
<child-component>
  <!-- Inside child, to get parent's data: -->
  ${$parent.parentProperty}
</child-component>
```

### 5. The `$host` Keyword

In slot projections, `$host` gives you access to the component that defines the slot:

```html
<!-- my-card.html (defines slots) -->
<div class="card">
  <slot></slot>
</div>

<!-- Usage with projected content -->
<my-card>
  <p>Card title: ${$host.title}</p>  <!-- Accesses my-card's title -->
</my-card>
```

## Debugging Scopes

When you need to debug scope issues, you can access the scope in the browser console:

```typescript
// In your component, expose the scope for debugging
export class DebugComponent {
  created() {
    (window as any).debugScope = this.$controller.scope;
  }
}
```

Then in the browser console:

```javascript
// Explore the scope structure
debugScope.bindingContext      // Your component instance
debugScope.overrideContext     // Special contextual values
debugScope.parent              // Parent scope (if any)

// Check if it's a component boundary
debugScope.isBoundary
```

## Best Practices

### 1. Keep Component Boundaries in Mind

Always remember that component boundaries exist. If you need parent data, be explicit:

```html
<!-- Good: Explicit about crossing boundaries -->
<div>${$parent.parentProperty}</div>

<!-- Confusing: Relies on scope traversal -->
<div>${parentProperty}</div>
```

### 2. Use Override Context Sparingly

Override context is powerful but can be confusing. Use it for:

* Template controller values (`$index`, `$first`, etc.)
* Temporary view-only values (`let` bindings)
* Slot projection context (`$host`)

Avoid it for regular component data.

### 3. Set Up Override Context Early

If you need override context values, set them up during `binding` or earlier:

```typescript
public binding(): void {
  // Good: Set before binding establishment
  this.$controller.scope.overrideContext.customValue = 'something';
}
```

### 4. Debug Scope Issues Systematically

When debugging scope issues:

1. Check the current scope structure
2. Verify component boundaries
3. Trace the property resolution path
4. Test with explicit `$parent` usage

## Summary

Scope and binding context are the foundation of Aurelia's data binding system. Understanding them helps you:

* Write more predictable binding expressions
* Debug data binding issues effectively
* Use advanced features like slot projections
* Create more maintainable component hierarchies

Remember the key concepts:

* **Binding context** = your component's data
* **Override context** = special contextual values
* **Component boundaries** = where automatic scope traversal stops
* **`$parent`** = explicit parent access
* **`$host`** = slot projection context

With this knowledge, you're well-equipped to master Aurelia's data binding system and build sophisticated, data-driven applications!

{% hint style="info" %}
**Want to learn more?** Check out our guides on [Custom Attributes](https://github.com/aurelia/aurelia/blob/master/docs/user-docs/components/custom-attributes.md), [Template Controllers](https://github.com/aurelia/aurelia/blob/master/docs/user-docs/templates/template-controllers.md), and [Shadow DOM and Slots](/components/shadow-dom-and-slots.md) to see scope and binding context in action.
{% endhint %}


---

# 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/components/scope-and-binding-context.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.
