Accessing Parent App from Child

I want to be able to access parent app shell (a side bar and top nav for my website) from the child app (the main page). I have filters that are clicked in the sidenav that I need to be able to track the state of from my child component in my router-view so that I can update data. I am very new to Aurelia so I don’t know if this is the best practice or if I’m completely approaching the problem wrong.

2 Likes

There are a couple ways that I’ve used to accomplish this.

  1. Events - Have parent/child VMs listen for and fire events in order to communicate changes.
  2. Application level settings - Store values in a class that is injected into any VMs that need to be aware of changes.

Examples

//app.js  
import {EventAggregator} from 'aurelia-event-aggregator';
import {AppSettings} from './my-settings';

export class App{
    message = "";

    static inject = [EventAggregator, AppSettings];
    constructor(eventAggregator, appSettings){
        this.eventAggregator = eventAggregator;
        this.settings = appSettings;

         //Set up an event listener/handler
         this.sub = this.eventAggregator.subscribe("userchange", payload => {
              this.userId = payload.id;  
              this.message = "User has been changed";
    }

   //Note: I'm assuming you'd define routes, etc.

    detached(){
         if(this.sub)
             this.sub.dispose();
     }
}

//app.html
<template>
    <div>${message}</div>
    <div>${settings.username}</div>
    <router-view></router-view>
</template>

//child.js
import {AppSettings} from '../my-settings';
import {EventAggregator} from 'aurelia-event-aggregator';

export class ChildRoute{
     selectedUser = null; 
     userList = [ ... ]  //Displayed for user to select a user

     static inject = [EventAggregator, AppSettings]
     constructor(eventAggregator, appSettings){
         this.eventAggregator = eventAggregator;
         this.settings = appSettings;
    }

    userSelectClick(user){
            this.settings.username = user.name;  //Should update in parent view
            this.eventAggregator.publish("userchange", { id: user.id});
     }
}

While this is a highly contrived example, it demonstrates both methods that I referred to. You can see in child.js that an event is published and that app.js is listening for that event. The child, then, is able to communicate a change up to the parent for the parent to respond to. In this example, we pass just the id in the event payload but you could pass whatever you want.

Also, notice in child.js the value of AppSettings.username is changed. Because this object is injected as a Singleton into the child VM and changes to the properties will be “seen” by the parent since the parent has bound to those properties in it’s view.

Hope that all makes sense. Maybe there are other ways to go about this, but these are the only two that I’m aware of.

1 Like