Skip to content

Applications: Foreground Applications

What are we learning here?

  • Application components will be loaded by default into the level foreground

Application components can be dragged only inside of the area of the stage in which it was loaded. Application components can be used to host complete applications or used for toolbox-windows or permanent displaying informations.

Applications will be loaded by default into the level foreground. So they don't collide with other components in the same stage loaded in other levels.

To demonstrate how to use application components in combination with other components, we have to do some preparations first.

(1) Extend our widget loading-components that holds just a placeholder all the time (replace the placeholder paragraph).

We extend the HTML structure and then we extend the component class.

  • We add an option target to pass a compenent instance. If not set the stages of the parent component will be used to load components.
  • Implement a simple click handler logic which will take the function name from the attribute data-role.
  • Add two functions which will load our mockup application that we have already implemented into the stage set into the main stage of target:

src/demo/components/loading-components/index.html

1
2
3
4
5
6
7
8
9
<div class="border rounded d-inline-block p-1 mr-2 my-1 bg-white text-dark">
  App
  <button class="btn btn-xs btn-info" data-role="appNoId">
    <i style="pointer-events: none" class="fas fa-times-circle"></i>
  </button>
  <button class="btn btn-xs btn-info" data-role="appId">
    <i style="pointer-events: none" class="pe-none fas fa-check-circle"></i>
  </button>
</div>

src/demo/components/loading-components/index.js

import { Canvas } from "@codecoupler/cc-ui";
import Mockup from "../../apps/mockup";
import { toRaw } from "vue";
import template from "./index.html";
export default class extends Canvas {
  static defaults = { target: null };
  async start() {
    this.element.innerHTML = template;
    this.element.addEventListener("click", (e) => {
      if (e.target.dataset.role) this[e.target.dataset.role]();
    });
    this.target = toRaw(this.options.target) ?? this.env.parent;
  }
  appNoId() {
    this.target.stage.load(Mockup);
  }
  appId() {
    this.target.stage.load(Mockup, "fixed-id");
  }
}

(2) Pass the option target in some places we load the component loading-components:

src/root.js

import { Component, Flexbox } from "@codecoupler/cc-ui";
import LoadingComponents from "./demo/components/loading-components";
import TestApp from "./demo/apps/canvas-vs-widget-layout";
export default class extends Component {
  async start() {
    await this.stage.load(Flexbox, {
      root: {
        type: "column",
        content: [
          { type: "stage", id: "top", class: "card-header" },
          { type: "stage", id: "$", grow: true }
        ]
      }
    });
    await this.getStage("top").load(LoadingComponents, { target: this });
    await this.stage.load(TestApp);
  }
}

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

import { Application, Buttons, Flexbox } from "@codecoupler/cc-ui";
import LoadingComponents from "../../components/loading-components";
import Content from "./content.js";
export default class extends Application {
  static defaults = {
    "@codecoupler": {
      panel: {
        panelSize: "1000 510",
        headerTitle: "Test Flexbox Features",
        footerToolbar: true
      }
    }
  };
  async start() {
    await this.stage.load(Content);
    await this.getStage("footer").load(Flexbox, {
      "@codecoupler": {
        flexbox: {
          root: {
            type: "row",
            content: [
              { type: "stage", id: "ftr-left", grow: true },
              { type: "stage", id: "$" }
            ]
          }
        }
      }
    });
    await this.getStage("ftr-left").load(LoadingComponents, { target: this });
    await this.getStage("footer").load(Buttons, {
      buttons: "close",
      context: this
    });
  }
}

You see the new buttons in three different places:

  • In the header of the root component: Loading into the main stage of the root component.
  • In the footer of the application component: Loading into the main stage of the application component.
  • Inside the content area of the application component: Loading into the main stage of the widget component component-basic.

Try all of them and drag the mockup application around to see the different areas in which the application can be dragged.

Furthermore one of the two buttons will use a fixed id to load the application:

  • × loads an application without an and in this case every application (or any other component) will get a random id. You can start as many you want.
  • use the signature this.load(ComponentType, Id) and load the application with an specific id. As we already know loading components with an already existing id will front them and not load them a second time. You can load only one application with this id.
Try it with the vue version

If you change in root.js the importing path from:

import TestApp from "./demo/apps/components-basics";

to:

import TestApp from "./demo/apps/components-basics-vue";

you can test the features with the vue version of the first application.