AUR0507

Error Message

AUR0507: Observer for bindable property <property> does not support coercion.

Where <property> is the name of the bindable property defined with a coerce function.

Description

This error occurs when a custom element defines a bindable property using the @bindable decorator (or the bindables static property) and provides a coerce function in its definition, but the mechanism Aurelia uses to observe changes to that property does not support applying this coercion function.

Cause

Aurelia's observation system uses different strategies to monitor property changes. Standard property observation on view model instances typically supports coercion. However, this error might arise in less common scenarios:

  1. Custom Observation Strategy: If a custom property observation strategy is registered or used for the specific property being bound, that custom strategy might not implement the necessary interface or logic to handle the coerce function defined in the bindable definition.

  2. Non-Standard Property Definition: The property being bound might be defined in a way (e.g., using Object.defineProperty with only a getter, or other non-standard configurations) that prevents Aurelia's default observer from applying coercion correctly.

  3. Internal Framework Issue (Unlikely): A potential mismatch between the bindable definition processing and the observer selection/initialization within the framework.

The most typical usage of @bindable with coercion should work:

import { bindable } from 'aurelia';

export class MyComponent {
  @bindable({ coerce: value => Number(value || 0) })
  public count: number = 0; // Standard usage, typically works

  @bindable({ coerce: value => typeof value === 'string' ? value === 'true' : Boolean(value) })
  public active: boolean = false; // Standard usage, typically works
}

The error implies that the observer assigned to count or active (or a similar property) lacks the capability to call the provided coerce function when a new value is set.

Solution

  1. Review Property Definition: Ensure the bindable property is defined as a standard class property on the view model. Avoid complex getter/setter implementations unless necessary, and ensure setters are present if needed for observation.

  2. Check for Custom Observers: Determine if any custom observation logic or configuration is applied to the specific property or the view model type. If so, ensure the custom observer correctly implements coercion handling if it intends to support bindables with coerce functions. This typically involves checking for a coerce function on the property definition and applying it within the observer's setValue or equivalent method.

  3. Simplify Coercion: As a workaround, if the underlying observation mechanism cannot be changed, move the coercion logic out of the @bindable definition and into a property setter or the change handler method for the bindable.

Example

import { bindable, IObserverLocator, IBindingContext, LifecycleFlags } from 'aurelia';

// --- Standard working example ---
export class StandardComponent {
  @bindable({ coerce: Number })
  public value: number = 0;
}

// --- Scenario potentially causing the error ---

// Imagine a custom observer that doesn't handle coercion
class NonCoercingObserver {
  constructor(private obj: any, private key: string) {}
  getValue() { return this.obj[this.key]; }
  setValue(newValue: any) {
    // This observer IGNORES any coerce function defined on the bindable
    this.obj[this.key] = newValue;
  }
  // ... other observer methods (subscribe, etc.) ...
  subscribe() {}
  unsubscribe() {}
  // Missing: Linkage to bindable definition's coerce function
}

// A custom element using this non-standard observation (hypothetical setup)
export class CustomObservedComponent {
  // Assume Aurelia is configured to use NonCoercingObserver for 'data'
  @bindable({ coerce: (v) => v * 2 }) // Coerce defined
  public data: number = 5;

  // When a binding like <custom-observed-component data.bind="source"></custom-observed-component>
  // is established, Aurelia might try to link the binding to the NonCoercingObserver.
  // During this setup (in Controller#addBinding), it sees the coerce function
  // but finds the observer doesn't support it, throwing AUR0507.
}

// --- Workaround: Move coercion to change handler ---
export class CoerceInHandlerComponent {
  @bindable({ changeHandler: 'dataChanged' })
  public data: number = 5; // No coerce function here

  private _internalData: number = 5;

  get processedData(): number {
    return this._internalData;
  }

  // Coercion logic moved here
  dataChanged(newValue: any) {
    this._internalData = Number(newValue || 0) * 2; // Apply coercion manually
    console.log('Coerced data:', this._internalData);
  }
}

Debugging Tips

  • Identify the specific bindable <property> mentioned in the error message.

  • Examine the definition of this property in the view model. Is it a standard property? Does it use @bindable with a coerce function?

  • Check the application's configuration for any custom observation setup (e.g., using ObserverLocator.addAdapter or similar APIs) that might affect this property.

  • Set breakpoints in Controller#addBinding (around line 1265 in templating/controller.ts) to inspect the bindable definition and the targetObserver instance selected for the property. Check the type of the targetObserver and whether it has methods or properties indicating coercion support (this might require inspecting Aurelia's internal observer interfaces/implementations).

  • Try removing the coerce function from the @bindable definition. If the error disappears, it confirms the issue is with applying coercion via the observer. Consider moving the logic as shown in the workaround example.

Last updated

Was this helpful?