LogoLogo
HomeDiscourseBlogDiscord
  • Introduction
  • Introduction
    • Quick start
    • Aurelia for new developers
    • Hello world
      • Creating your first app
      • Your first component - part 1: the view model
      • Your first component - part 2: the view
      • Running our app
      • Next steps
  • Templates
    • Template Syntax
      • Attribute binding
      • Event binding
      • Text interpolation
      • Template promises
      • Template references
      • Template variables
      • Globals
    • Custom attributes
    • Value converters (pipes)
    • Binding behaviors
    • Form Inputs
    • CSS classes and styling
    • Conditional Rendering
    • List Rendering
    • Lambda Expressions
    • Local templates (inline templates)
    • SVG
  • Components
    • Component basics
    • Component lifecycles
    • Bindable properties
    • Styling components
    • Slotted content
    • Scope and context
    • CustomElement API
    • Template compilation
      • processContent
      • Extending templating syntax
      • Modifying template parsing with AttributePattern
      • Extending binding language
      • Using the template compiler
      • Attribute mapping
  • Getting to know Aurelia
    • Routing
      • @aurelia/router
        • Getting Started
        • Creating Routes
        • Routing Lifecycle
        • Viewports
        • Navigating
        • Route hooks
        • Router animation
        • Route Events
        • Router Tutorial
        • Router Recipes
      • @aurelia/router-lite
        • Getting started
        • Router configuration
        • Configuring routes
        • Viewports
        • Navigating
        • Lifecycle hooks
        • Router hooks
        • Router events
        • Navigation model
        • Current route
        • Transition plan
    • App configuration and startup
    • Enhance
    • Template controllers
    • Understanding synchronous binding
    • Dynamic composition
    • Portalling elements
    • Observation
      • Observing property changes with @observable
      • Effect observation
      • HTML observation
      • Using observerLocator
    • Watching data
    • Dependency injection (DI)
    • App Tasks
    • Task Queue
    • Event Aggregator
  • Developer Guides
    • Animation
    • Testing
      • Overview
      • Testing attributes
      • Testing components
      • Testing value converters
      • Working with the fluent API
      • Stubs, mocks & spies
    • Logging
    • Building plugins
    • Web Components
    • UI virtualization
    • Errors
      • Kernel Errors
      • Template Compiler Errors
      • Dialog Errors
      • Runtime HTML Errors
    • Bundlers
    • Recipes
      • Apollo GraphQL integration
      • Auth0 integration
      • Containerizing Aurelia apps with Docker
      • Cordova/Phonegap integration
      • CSS-in-JS with Emotion
      • DOM style injection
      • Firebase integration
      • Markdown integration
      • Multi root
      • Progress Web Apps (PWA's)
      • Securing an app
      • SignalR integration
      • Strongly-typed templates
      • TailwindCSS integration
      • WebSockets Integration
      • Web Workers Integration
    • Playground
      • Binding & Templating
      • Custom Attributes
        • Binding to Element Size
      • Integration
        • Microsoft FAST
        • Ionic
    • Migrating to Aurelia 2
      • For plugin authors
      • Side-by-side comparison
    • Cheat Sheet
  • Aurelia Packages
    • Validation
      • Validation Tutorial
      • Plugin Configuration
      • Defining & Customizing Rules
      • Architecture
      • Tagging Rules
      • Model Based Validation
      • Validation Controller
      • Validate Binding Behavior
      • Displaying Errors
      • I18n Internationalization
      • Migration Guide & Breaking Changes
    • i18n Internationalization
    • Fetch Client
      • Overview
      • Setup and Configuration
      • Response types
      • Working with forms
      • Intercepting responses & requests
      • Advanced
    • Event Aggregator
    • State
    • Store
      • Configuration and Setup
      • Middleware
    • Dialog
  • Tutorials
    • Building a ChatGPT inspired app
    • Building a realtime cryptocurrency price tracker
    • Building a todo application
    • Building a weather application
    • Building a widget-based dashboard
    • React inside Aurelia
    • Svelte inside Aurelia
    • Synthetic view
    • Vue inside Aurelia
  • Community Contribution
    • Joining the community
    • Code of conduct
    • Contributor guide
    • Building and testing aurelia
    • Writing documentation
    • Translating documentation
Powered by GitBook
On this page
  • The Big Picture: What is Scope?
  • The JavaScript Analogy
  • Anatomy of a Scope
  • 1. Binding Context: Your Data Home
  • Best Practices
  • 1. Keep Component Boundaries in Mind
  • 2. Use Override Context Sparingly
  • 3. Set Up Override Context Early
  • 4. Debug Scope Issues Systematically
  • Summary

Was this helpful?

Export as PDF
  1. Components

Scope and context

Master the art of scope and binding context - the secret sauce behind Aurelia's powerful data binding magic.

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.

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

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:

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:

Then in the browser console:
```javascript
// Explore the scope structure
debugScope.bindingContext
debugScope.overrideContext
debugScope.parent

// Test property resolution
Scope.getContext(debugScope, 'propertyName', 0)

Best Practices

1. Keep Component Boundaries in Mind

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

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

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!

Want to learn more? Check out our guides on Custom Attributes, Template Controllers, and Shadow DOM and Slots to see scope and binding context in action.

PreviousSlotted contentNextCustomElement API

Last updated 4 days ago

Was this helpful?