Au2: access parent component viewmodel in a clean way

In Aurelia 1 we had “Parent.of” resolver. I found this comment explaining why the Parent.of is no longer feasible in Au2: Injecting a parent’s custom attribute doesn’t work · Issue #660 · aurelia/aurelia · GitHub

However, I don’t see the actual recommended solution. Did everyone just settle on accessing this.$controller.parent.viewModel in a lifetime hook?

This feels awkward, kinda messing with internal API. Also we have a @children decorator in Au2, so there’s a clean way for a reverse link.

Am I missing some clean solution for accessing parent?

@migajek can you help with a repro to show the lack of capability?

Can’t you just inject the parent’s view model? Used to work in AU1 without any decorators.
Definitely works in aurelia2 gridstack plugin aurelia-gridstack/packages/aurelia-gridstack/src/elements/grid-stack-item/grid-stack-item.ts at au2 · aurelia-ui-toolkits/aurelia-gridstack · GitHub

See how Gridstack is injected into its’ children items

The issue you are facing is because the difference in the container structure in v2, compared to v1. In v1, custom attribute participates in the container hierarchy, while it doesn’t in v2.

Though there are still easy / official way to get the parent custom attributes:

Supposed we have the following dom, like in the GH issue:

<div au-dropdown>
  <div dropdown-toggle>
</div>

In the AuDropdownToggle attribute, you can search for AuDropdown controller in the link lifecycle like this:

class AuDropdownToggle {
  link(parentController) {
    const auDropDownController = parentController.children.at(-1);
    const auDropDown = auDropdownController.viewModel;
    ...
  }
}

Another way to get a custom attribute controller is to retrieve it based on DOM structure, like this:

import { resolve, CustomAttribute } from 'aurelia';
...
class AuDropdownToggle {
  constructor() {
    const host = resolve(Element);
    const dropdownEl = host.closest('[some-attribute-that-indicates-the-au-dropdown-usage]')
    const parentController = CustomAttribute.for(dropdownEl, 'au-dropdown')
  }
}
1 Like

A PR has been created to address this, pls have a look at feat(custom-attribute): ability to find closest attr by name or ctor by bigopon · Pull Request #1928 · aurelia/aurelia · GitHub

2 Likes

@bigopon thank you for the resolution. Sorry I was not able to provide examples on time, but it looks you got my intentions just right :slight_smile:

as a side note - I just realized link doesn’t seem to be documented lifecycle hook. Is that a mistake in the documentation, or is this some kind of internal API?