Passing the parent when parent is the same compone

2019-07-04 19:31发布

Edit: This question used to be titled "Getting parent via DI when parent is the same type in Aurelia" but due to how my elements are nested, it makes more sense to just bind the parent to the element, so the title has been changed to reflect this.

If I have a custom element, Thing which has a child Thing (which has a another child Thing, etc), how can I inject the parent instance when the class is the same?

export class Thing {
    static inject = [Thing]; // <-- no reference to Thing as we are inside the class
    constructor(parentThing) {
        this.parent = parentThing;
    }
}

As a further complexity, the root Thing element will have no parent, so the DI needs to allow for optional injection.

3条回答
手持菜刀,她持情操
2楼-- · 2019-07-04 20:08

I don't think your problem can be solved with DI. Thing has to be @transient if you want to have several instances of it. This means that the container will not hold references to things it creates.

查看更多
手持菜刀,她持情操
3楼-- · 2019-07-04 20:23

This problem doesn't look right or necessary to use DI. If an element need to receive some specific input data from its consumer, @bindable would be my natural first thinking. So how about creating a @bindable parentThing in Thing?

In other hand, if what you want is to access parent binding context, consider bind() component life cycle.

查看更多
三岁会撩人
4楼-- · 2019-07-04 20:26

Here's how to do that: https://gist.run?id=b075366d29f2400d3cc931f6fc26db24

app.html

<template>
  <require from="./thing"></require>

  <thing name="A">
    <thing name="B">
      <thing name="C">
        <thing name="D">
        </thing>
      </thing>
    </thing>
  </thing>
</template>

app.js

export class App {
}

optional-parent.js

import {resolver} from 'aurelia-dependency-injection';

@resolver()
export class OptionalParent {
  constructor(key) {
    this.key = key;
  }

  get(container) {
    if (container.parent && container.parent.hasResolver(this.key, false)) {
      return container.parent.get(this.key)
    }
    return null;
  }

  static of(key) {
    return new OptionalParent(key);
  }
}

thing.html

<template>
  <h3>
    My Name is "${name}".
    <span if.bind="parent">My parent's name is "${parent.name}".</span>
    <span if.bind="!parent">I don't have a parent.</span>
  </h3>
  <content></content>
</template>

thing.js

import {bindable, inject} from 'aurelia-framework';
import {OptionalParent} from './optional-parent';

@inject(OptionalParent.of(Thing))
export class Thing {
  @bindable name;

  constructor(parent) {
    this.parent = parent;
  }
}
查看更多
登录 后发表回答