Skip to content

Stages: Adressing Stages

The stages created by our canvas component can be accessed by parent components (in our case it is our application).

What are we learning here?

  • Components can be loaded with load(ComponentType,Id) which will set an id for addressing
  • Parent components can access these stages with this.getStage()

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
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");
    console.info(this.getStages());
  }
}

You will see an output like this:

Object { main {}, ... }
► main: Object {  }
► "main/a38ABDd_814fYSpmyNyYc/luigi": Object {  }
► "main/a38ABDd_814fYSpmyNyYc/mario": Object {  }
► "main/a38ABDd_814fYSpmyNyYc/peach": Object {  }
► "main/a38ABDd_814fYSpmyNyYc/daisy": Object {  }

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

But what is the cryptic part "a38ABDd_814fYSpmyNyYc" in the path? This is the id of the widget that keeps the stages. This id is a random string and not very usefull. So let's assign an id to the widget. As we have learned before you can assign an id to any component with the load signature load(ComponentType, Id):

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
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, "flexbox-canvas");
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
    console.info(this.getStages());
  }
}

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: Canvas,
  id: "flexbox-canvas"
})

Now you see in the console:

Object { main {}, ... }
► main: Object {  }
► "main/flexbox-canvas/luigi": Object {  }
► "main/flexbox-canvas/mario": Object {  }
► "main/flexbox-canvas/peach": Object {  }
► "main/flexbox-canvas/daisy": Object {  }

Let's load components into this stages. For this we will use this.getStage(...) to get a specific stage instead of the "main" and then we apply the method load() to the returned stage object.

In order to have enough widgets, we borrow all of them from our previous applications and load them into our stages.

We will start loading our first component into the stage named mario:

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
import {
  Application,
  Canvas,
  Tools,
  CenteredMessage
} 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, "flexbox-canvas");
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
    await this.getStage("mario").load(CenteredMessage, {
      text: "Stage Mario"
    });
    console.info(this.getStages());
  }
}

Before we continue, we would like to clarify the following: We used now the stage name header instead the full qualified path main/flexbox-canvas/header. This is possible because their is no other stage with a name header and therefore the name will be replaced with a glob pattern **/header. And this leads to only one stage.

This makes it clear that we can also use glob patterns. Let's try the glob pattern with a second component. We use our widget we have created before:

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,
  Canvas,
  Tools,
  CenteredMessage
} from "@codecoupler/cc-ui";
import MainTemplate from "./layout.html";
import WidgetBasics from "../widget-basics/content.js";
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, "flexbox-canvas");
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
    await this.getStage("mario").load(CenteredMessage, {
      text: "Stage Mario"
    });
    await this.getStage("**/luigi").load(WidgetBasics, {
      myWidgetArg1: "Value 1"
    });
    console.info(this.getStages());
  }
}

And here another variation for the next stage:

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
import {
  Application,
  Canvas,
  Tools,
  CenteredMessage
} from "@codecoupler/cc-ui";
import MainTemplate from "./layout.html";
import WidgetBasics from "../widget-basics/content.js";
import SingleRoot from "../single-root/content.js";
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, "flexbox-canvas");
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
    await this.getStage("mario").load(CenteredMessage, {
      text: "Stage Mario"
    });
    await this.getStage("**/luigi").load(WidgetBasics, {
      myWidgetArg1: "Value 1"
    });
    await this.getStage("main/*/peach").load(SingleRoot, {
      myWidgetArg1: "Value 1"
    });
    console.info(this.getStages());
  }
}

And last but not least the full path to the stage:

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
import {
  Application,
  Canvas,
  Tools,
  CenteredMessage
} from "@codecoupler/cc-ui";
import MainTemplate from "./layout.html";
import WidgetBasics from "../widget-basics/content.js";
import SingleRoot from "../single-root/content.js";
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, "flexbox-canvas");
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
    await this.getStage("mario").load(CenteredMessage, {
      text: "Stage Mario"
    });
    await this.getStage("**/luigi").load(WidgetBasics, {
      myWidgetArg1: "Value 1"
    });
    await this.getStage("main/*/peach").load(SingleRoot, {
      myWidgetArg1: "Value 1"
    });
    await this.getStage("main/flexbox-canvas/daisy").load(CenteredMessage, {
      text: "Stage Peach"
    });
    console.info(this.getStages());
  }
}

Let's have a look again into the console:

Object { main {}, ... }
► main: Object {  }
► "main/flexbox-canvas/daisy": Object {  }
► "main/flexbox-canvas/luigi": Object {  }
► "main/flexbox-canvas/luigi/LXwxmaPtKUk6g3m8RH_YP/_T6zdx8w6ZtOeJbbKgRO3": Object {  }
► "main/flexbox-canvas/mario": Object {  }
► "main/flexbox-canvas/peach": Object {  }
► "main/flexbox-canvas/peach/a-71akzes5jhInqUmAMaU/Q_M6XbptAI9uyS6clFE1x": Object {  }

You will see new stages inside of the stages "peach" and "luigi". This is our stage that we have created in our widget component. You see you can address even stages in deeper levels and nested components.

Maybe one last optimization. After loading our first widget which provides the new stages, all other stages must not be loaded sequentially. We can combine the loading of all other widgets into one promise:

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
import {
  Application,
  Canvas,
  Tools,
  CenteredMessage
} from "@codecoupler/cc-ui";
import MainTemplate from "./layout.html";
import WidgetBasics from "../widget-basics/content.js";
import SingleRoot from "../single-root/content.js";
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, "flexbox-canvas");
    main.element.replaceWith(MainTemplate);
    Tools.registerStages(main, main.element, "public");
    await Promise.all([
      this.getStage("mario").load(CenteredMessage, {
        text: "Stage Mario"
      }),
      this.getStage("**/luigi").load(WidgetBasics, {
        myWidgetArg1: "Value 1"
      }),
      this.getStage("main/*/peach").load(SingleRoot, {
        myWidgetArg1: "Value 1"
      }),
      this.getStage("main/flexbox-canvas/daisy").load(CenteredMessage, {
        text: "Stage Peach"
      })
    ]);
    console.info(this.getStages());
  }
}