Skip to content

Stages: Creating Multiple Stages

A component can create as many stages as needed. We are now considering the case where we use a component to define a layout with multiple stages in which several widgets are loaded. We will look now how to build such a layout with the flexbox model.

Furthermore, we want a component to create the stages and the parent component to use them. Therefore we have to mark them as "public" and provide them with an id.

What are we learning here?

  • Stages with this.registerStage(Element,Id,Access) will set an id for addressing and the access level
  • Stages can also be created with Tools.resgisterStages(this, this.element) in conjunction with the HTML attribute data-cc-stage

We create a layout based on flexbox and put the file in a new subfolder:

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

 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
<div class="h-100 border border-success d-flex flex-column">
  <div class="p-2 flex-grow-1 d-flex flex-row">
    <div class="w-25 flex-grow-1 d-flex flex-column p-2">
      <div>Stage "mario"</div>
      <div
        data-cc-stage="mario"
        class="flex-grow-1 border border-primary"
      ></div>
    </div>
    <div class="w-25 flex-grow-1 d-flex flex-column p-2">
      <div>Stage "luigi"</div>
      <div
        data-cc-stage="luigi"
        class="flex-grow-1 border border-primary"
      ></div>
    </div>
  </div>
  <div class="p-2 flex-grow-1 d-flex flex-row">
    <div class="w-25 flex-grow-1 d-flex flex-column p-2">
      <div>Stage "peach"</div>
      <div
        data-cc-stage="peach"
        class="flex-grow-1 border border-primary"
      ></div>
    </div>
    <div class="w-25 flex-grow-1 d-flex flex-column p-2">
      <div>Stage "daisy"</div>
      <div
        data-cc-stage="daisy"
        class="flex-grow-1 border border-primary"
      ></div>
    </div>
  </div>
</div>

Now we create our new component. We have already learned, that we can create a stage with the method registerStage(). So we could do here something like:

this.registerStage(this.element.find("[data-cc-stage=mario]"), "mario", "public");
this.registerStage(this.element.find("[data-cc-stage=luigi]"), "luigi", "public");
this.registerStage(this.element.find("[data-cc-stage=peach]"), "peach", "public");
this.registerStage(this.element.find("[data-cc-stage=daisy]"), "daisy", "public");

As you can see that we create a stage with the method this.registerStage() with two more arguments. The second argument is an id with which we can later address the stage and the third argument is the access level which is by default "private". With "public" you specify that this stage can also be addressed by parent components

You can simplify the above commands and replace them with only one. The module Tools offers a simple method named registerStages(component,element,access) to convert all elements that have the attribute data-cc-stage into a stage. The value of the attribute is then used as the id of the stage.

So theoretically we would have to create a canvas component that only loads the template and creates the stages. That would be only two lines of code in a boilerplate of eight lines in total. Not particularly efficient:

import { Canvas, Tools } from "@codecoupler/cc-ui";
import template from "./layout.html";
export default class extends Canvas {
  async start() {
    this.element.replaceWith(template);
    Tools.registerStages(this, this.element, "public");
  }
}

Info

If you use a canvas cmponent and create a top-level element that is used just for building a layout, you should always use replaceWith() instead html(). This saves one div element.

For cases where you need to create a component that consists of only a few lines of code, you should take advantage of the fact that this.element is accessible from parent components.

We will now load the Canvas component itself (without writing our own derived class) and fill the element of the canvas component directly in the new application component:

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import { Application, Canvas, Tools } from "@codecoupler/cc-ui";
import MainTemplate from "./layout.html";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "1200 580",
        headerTitle: "Test Stage Features"
      }
    }
  };
  async start() {
    let main = await this.stage.load(Canvas);
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
  }
}

We load the new application in our system.js file (just by replacing the previous one):

src/system.js

1
2
3
4
5
6
7
import { Component } from "@codecoupler/cc-ui";
import TestApp from "./demo/apps/stages-flexbox";
export default class extends Component {
  async boot() {
    await this.stage.load(TestApp);
  }
}

Now we have a nice application which provide four empty stages.