AUR0504
Error Message
AUR0504: Synthetic view at <ControllerName> is being activated with null/undefined scope.
Where <ControllerName> is the name of the controller for the synthetic view.
Description
This error occurs when Aurelia attempts to activate a "synthetic" view controller, but the necessary binding scope is missing (null or undefined). Synthetic views are typically views created dynamically or manually (not through standard template compilation and custom element definition), and they require an explicit scope to be provided during activation because they don't automatically inherit scope in the same way standard components do.
Cause
Manual View Creation/Activation: You might be manually creating a view using
IViewFactoryand then attempting to activate its controller without providing a valid scope object during thecontroller.activate()call.Dynamic Composition Issues: Custom logic involving dynamic composition (e.g., using low-level rendering APIs) might fail to propagate or provide the required scope to a dynamically created view before activating it.
Incorrect API Usage: Using internal or advanced Aurelia APIs related to view/controller creation without fully understanding the requirement to supply a scope for synthetic views.
Solution
Provide Scope During Activation: When manually activating a synthetic view controller, ensure you pass a valid
IScopeobject as part of the activation context. The scope typically includes the binding context (often the parent view model or a specific data object) and any necessary override contexts.Use Standard Composition: Prefer using standard Aurelia mechanisms for composition like
<au-compose>or template controllers (if.bind,repeat.for, etc.) whenever possible, as they handle scope propagation automatically.Review Dynamic Logic: If manual creation is necessary, carefully review the code that creates and activates the synthetic view. Ensure a scope, derived correctly from the parent or context, is created and passed during activation. Use
Scope.create(bindingContext, parentScope | null)orScope.fromParent(parentScope, bindingContext)to create appropriate scopes.
Example
import {
IViewFactory,
Scope,
ICustomElementController,
ISyntheticView, // Represents the controller for a synthetic view
Controller // Low-level API
} from 'aurelia'; // Adjust imports as needed
export class ManualCompositionViewModel {
public viewFactory!: IViewFactory; // Assume this is injected or created
public parentController!: ICustomElementController<this>; // Assume available
public dynamicView: ISyntheticView | null = null;
async createAndShowView() {
// Create the view
this.dynamicView = this.viewFactory.create();
// --- Incorrect: Activating without providing scope ---
try {
// This might throw AUR0504 because synthetic views need an explicit scope
await this.dynamicView.activate(this.parentController);
} catch (e) {
console.error("Activation failed (potentially AUR0504):", e);
}
// --------------------------------------------------
// --- Correct: Creating and providing scope ---
// Define the data context for the new view
const bindingContext = { message: 'Hello from dynamic view!' };
// Create a scope for the view, linking it to the parent scope
const scope = Scope.fromParent(this.parentController.scope, bindingContext);
try {
// Activate with the created scope
await this.dynamicView.activate(this.parentController, null, { scope: scope });
// Attach the view to the DOM (simplified)
this.dynamicView.appendTo(document.body /* or some target element */);
} catch (e) {
console.error("Corrected activation failed:", e);
}
// ---------------------------------------------
}
async createAndShowViewWithLowLevelController() {
// --- Low-level Controller example ---
const host = document.createElement('div');
const definition = Controller.getDefinition(class MyData {}); // Get definition if needed
const lowLevelController = Controller.forSyntheticView(
this.parentController.container.get(IViewFactory), // Usually need factory
definition,
this.parentController.container
);
// --- Incorrect: Activating without scope ---
try {
await lowLevelController.activate(this.parentController, host); // Missing scope
} catch(e) {
console.error("Low-level activation failed (potentially AUR0504):", e);
}
// --- Correct: Activating with scope ---
const bindingContext = { info: 'Low level view data' };
const scope = Scope.fromParent(this.parentController.scope, bindingContext);
try {
await lowLevelController.activate(this.parentController, host, { scope }); // Provide scope
console.log("Low-level activation successful.");
} catch(e) {
console.error("Corrected low-level activation failed:", e);
}
}
}
class MyData {} // Example class for definitionDebugging Tips
Identify the component or code location where the synthetic view is being created and activated.
Examine the parameters being passed to the
controller.activate()method for the synthetic view. Is a scope object being included?Inspect the value of the scope being passed. Is it correctly created using
Scope.createorScope.fromParent? Does it contain the expected binding context?Set breakpoints in the
Controller#activatemethod (around line 543 intemplating/controller.ts) to inspect the controller type (isCustomElement,isSynthetic), the providedactivationContext, and the resultingscope.Consider if standard Aurelia composition features can achieve the same result more simply and robustly, avoiding the need for manual synthetic view management.
Last updated
Was this helpful?