Skip to content

Addressing: Adressing Components

What are we learning here?

  • A component can be adressed with the stage method getComponent()
  • Parent components can access components in child stages with the component method getComponent()

You can address components in two ways. On the one hand, you can first determine the desired stage with the component method getStage() and then access the desired component using the stage method getComponent().

On the other hand, you can use the component method getComponent (yes, it's the same name like the stage method). This basically combines both previous calls. Accessing components this way is very similar to accessing from Stages as you can use glob patterns for example. Let's extend our application and add a console output:

src/demo/apps/stages-flexbox/index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { Application, Message } from "@codecoupler/cc-ui";
import Content from "./content.js";
import Child from "./child.js";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "580 580",
        headerTitle: "Test Stage Features"
      }
    }
  };
  async start() {
    await this.stage.load(Content, "flexbox-canvas");
    await Promise.all([
      this.getStage("mario").load(Child, "child-of-mario"),
      this.getStage("**/luigi").load(Child, "child-of-luigi"),
      this.getStage("main/*/peach").load(Child, "child-of-peach"),
      this.getStage("main/flexbox-canvas/daisy").load(Child, "child-of-daisy")
    ]);
    await Promise.all([
      this.getStage("**/child-of-mario/child-stage").load(Message),
      this.getStage("**/child-of-luigi/child-stage").load(Message),
      this.getStage("**/child-of-peach/child-stage").load(Message),
      this.getStage("**/child-of-daisy/child-stage").load(Message)
    ]);
    console.info(this.getStages());
    console.info(this.getComponents());
  }
}

You will see an output like this:

Object { main {}, ... }
► "main/flexbox-canvas": Object { ... }
► "main/flexbox-canvas/daisy/child-of-daisy": Object {  }
► "main/flexbox-canvas/daisy/child-of-daisy/child-stage/y0brHen0cunT0teSaREAg": Object {  }
► "main/flexbox-canvas/luigi/child-of-luigi": Object {  }
► "main/flexbox-canvas/luigi/child-of-luigi/child-stage/nLhCDcIq0QorWsCK0undb": Object {  }
► "main/flexbox-canvas/mario/child-of-mario": Object {  }
► "main/flexbox-canvas/mario/child-of-mario/child-stage/WH1r0QtnZx0zYWdE_N8Ot": Object {  }
► "main/flexbox-canvas/peach/child-of-peach": Object {  }
► "main/flexbox-canvas/peach/child-of-peach/child-stage/CZLfx7Ig_MWXAA_4lQyM7": Object {  }

These are the paths to every component that is accessible from the application. As you see the path starts always with the "main" stage of the application itself.

The cryptic parts like "y0brHen0cunT0teSaREAg" in the path are the id of the Message components which we did not assign an id. Let's assign an id to these components:

src/demo/apps/stages-flexbox/index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import { Application, Message } from "@codecoupler/cc-ui";
import Content from "./content.js";
import Child from "./child.js";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "580 580",
        headerTitle: "Test Stage Features"
      }
    }
  };
  async start() {
    await this.stage.load(Content, "flexbox-canvas");
    await Promise.all([
      this.getStage("mario").load(Child, "child-of-mario"),
      this.getStage("**/luigi").load(Child, "child-of-luigi"),
      this.getStage("main/*/peach").load(Child, "child-of-peach"),
      this.getStage("main/flexbox-canvas/daisy").load(Child, "child-of-daisy")
    ]);
    await Promise.all([
      this.getStage("**/child-of-mario/child-stage").load(
        Message,
        "message-of-mario"
      ),
      this.getStage("**/child-of-luigi/child-stage").load(
        Message,
        "message-of-luigi"
      ),
      this.getStage("**/child-of-peach/child-stage").load(
        Message,
        "message-of-peach"
      ),
      this.getStage("**/child-of-daisy/child-stage").load(
        Message,
        "message-of-daisy"
      )
    ]);
    console.info(this.getStages());
    console.info(this.getComponents());
  }
}

Start Definition Object vs Shortcut Signature

We will use here a signature of the load method which expects a Component and an id. This is just a shortcut signature. The load method normally expects a so called start definition object. This would look like:

load({
  component: Message,
  id: "message-of-mario"
})

Now you see in the console:

► "main/flexbox-canvas": Object { ... }
► "main/flexbox-canvas/daisy/child-of-daisy": Object {  }
► "main/flexbox-canvas/daisy/child-of-daisy/child-stage/message-of-daisy": Object {  }
► "main/flexbox-canvas/luigi/child-of-luigi": Object {  }
► "main/flexbox-canvas/luigi/child-of-luigi/child-stage/message-of-luigi": Object {  }
► "main/flexbox-canvas/mario/child-of-mario": Object {  }
► "main/flexbox-canvas/mario/child-of-mario/child-stage/message-of-mario": Object {  }
► "main/flexbox-canvas/peach/child-of-peach": Object {  }
► "main/flexbox-canvas/peach/child-of-peach/child-stage/message-of-peach": Object {  }

Let's now access these components from our parent application component and change some options (a message component can be used without namespaced options. The passed options will be mapped automatically into the correct namespace):

src/demo/apps/stages-flexbox/index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { Application, Message } from "@codecoupler/cc-ui";
import Content from "./content.js";
import Child from "./child.js";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "580 580",
        headerTitle: "Test Stage Features"
      }
    }
  };
  async start() {
    await this.stage.load(Content, "flexbox-canvas");
    await Promise.all([
      this.getStage("mario").load(Child, "child-of-mario"),
      this.getStage("**/luigi").load(Child, "child-of-luigi"),
      this.getStage("main/*/peach").load(Child, "child-of-peach"),
      this.getStage("main/flexbox-canvas/daisy").load(Child, "child-of-daisy")
    ]);
    await Promise.all([
      this.getStage("**/child-of-mario/child-stage").load(
        Message,
        "message-of-mario"
      ),
      this.getStage("**/child-of-luigi/child-stage").load(
        Message,
        "message-of-luigi"
      ),
      this.getStage("**/child-of-peach/child-stage").load(
        Message,
        "message-of-peach"
      ),
      this.getStage("**/child-of-daisy/child-stage").load(
        Message,
        "message-of-daisy"
      )
    ]);
    this.getStage("**/child-of-luigi/child-stage").getComponent(
      "message-of-luigi"
    ).options = {
      text: "Message of Luigi!",
      class: "bg-success text-white"
    };
    this.getComponent("message-of-mario").options = {
      text: "Message of Mario!",
      class: "bg-success text-white"
    };
    console.info(this.getStages());
    console.info(this.getComponents());
  }
}

In the first approach we use the classic way of getting a stage and then getting a component of this stage. It's quite a long line.

In the second approach we used the getComponent method of a component and just the component id message-of-mario instead the full qualified path main/flexbox-canvas/mario/child-of-mario/child-stage/message-of-mario. This is possible because their is no other component with a name message-of-mario and therefore the name will be replaced with a glob pattern **/message-of-mario. And this leads to only one component.