Skip to content

Addressing: Replacing Stages

What are we learning here?

  • Components that provide stages named $ replace their parent stages

There is a special id for stages: $. Stages with such an id will replace the parent stage. Components which provide such stages can modify a layout of an application without the need to change the code you have already written. We will now show this with a concrete example.

Let's start with an HTML structure in a separate file which divide the entire space into two parts, a top and a bottom section:

src/demo/apps/stages-flexbox/header.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<div class="h-100 d-flex flex-column">
  <div
    class="flex-grow-0 bg-primary text-white p-2"
    data-cc-stage="top"
    data-cc-stage-access="public"
  ></div>
  <div
    class="flex-grow-1"
    data-cc-stage="$"
    data-cc-stage-access="public"
  ></div>
</div>

Now we create a new canvas component which provide these two parts as stages. As you can see above the top stage will get the id top and the bottom stage the id $:

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

1
2
3
4
5
6
7
8
import { Canvas } from "@codecoupler/cc-ui";
import template from "./header.html";
export default class extends Canvas {
  async start() {
    this.element.replaceWith(template);
    this.element.registerStages();
  }
}

We will now load the canvas component in front of our existing code:

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
53
54
55
import { Application, Message } from "@codecoupler/cc-ui";
import Content from "./content.js";
import Child from "./child.js";
import Header from "./header.js";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "580 580",
        headerTitle: "Test Stage Features"
      }
    }
  };
  async start() {
    await this.stage.load(Header, "header-canvas");
    this.getStage("main/header-canvas/top").load(Message);
    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());
  }
}

The new canvas component replace in this case the main stage of the application with its own bottom stage. All the following code was leaved untouched.

All following addresses pointing to the main stage stage will be redirected to the new bottom stage. For example main/flexbox-canvas/peach is in fact main/header-canvas/$/flexbox-canvas/peach.

Let's look into the console. You won't find any mention of stage $:

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

There is another method which can help you to understand the complete stage addressing. Very useful for Debuging:

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
53
54
55
56
import { Application, Message } from "@codecoupler/cc-ui";
import Content from "./content.js";
import Child from "./child.js";
import Header from "./header.js";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "580 580",
        headerTitle: "Test Stage Features"
      }
    }
  };
  async start() {
    await this.stage.load(Header, "header-canvas");
    this.getStage("main/header-canvas/top").load(Message);
    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());
    console.info(this.getStagesDebug());
  }
}

Now you can see all "real" paths without the replacing:

Object { main {}, ... }
► main: Object {  }
► "main/header-canvas/$": Object {  }
► "main/header-canvas/$/flexbox-canvas/daisy": Object {  }
► "main/header-canvas/$/flexbox-canvas/daisy/child-of-daisy/child-stage": Object {  }
► "main/header-canvas/$/flexbox-canvas/luigi": Object {  }
► "main/header-canvas/$/flexbox-canvas/luigi/child-of-luigi/child-stage": Object {  }
► "main/header-canvas/$/flexbox-canvas/mario": Object {  }
► "main/header-canvas/$/flexbox-canvas/mario/child-of-mario/child-stage": Object {  }
► "main/header-canvas/$/flexbox-canvas/peach": Object {  }
► "main/header-canvas/$/flexbox-canvas/peach/child-of-peach/child-stage": Object {  }
► "main/header-canvas/top": Object {  }