Skip to content

CodeCoupler UI Stage

Danger

This is the old 2.x Version! A new version was never completed!

Overview

A stage is a class derived from the base class Stage. A stage manipulates the current stage and provides one element which will be the new stage from then on.

Only some components like System or Application are "stageable".

A stage is always the target container for components started from a parent component.

In case of a System is the parent component all application that will be started will run in the current stage. Any application will always maximize to the whole stage and can be moved them only within the current stage.

TODO

Describe a Stage in an Application context

With a stage instance you can divide the current stage into different areas and define a new stage:

After a system initialization:

┌───────────────────────────┐
│                           │
│    Your container         │
│    at beginning           │
│                           │
│    This is the main       │
│    stage where all apps   │
│    will be started        │
│                           │
│                           │
└───────────────────────────┘

After adding a new stage object:

┌───┬───────────────────────┐
│   │                       │
│   │  <- Define here a     │
│   │     sidebar container │
│   │                       │
│   │  The remaining space  │
│   │  is your new main     │
│   │  stage where all apps │
│   │  will be started      │
│   │                       │
└───┴───────────────────────┘

Stages can be nested. It means that after you add your first stage, you can add another one which will divide the main stage again.

┌───┬───────────────────────┐
│   │                       │
│   ├───────────────────────┤
│   │  ^ Define a new header│
│   │                       │
│   │  The remaining space  │
│   │  is your new main     │
│   │  stage where all apps │
│   │  will be started      │
│   │                       │
└───┴───────────────────────┘

And so on.

Start a Stage

Instantiate

You cannot initialize a Stage class directly. A stage can be started over the factory method stage(stageStart) of a stagable component. The factory method starts a new stage in the current stage.

1
this.stage(stageStart);

Stages can also be defined in the stages options of a System instance.

1
2
3
4
5
6
7
8
//Just one Stage:
new System({
  stages: stageStart,
});
//Multiple Stages:
new System({
  stages: [stageStart1, stageStart2, stageStart3],
});

If the current stage is not empty an error will be thrown!

Error Handling

If any error occurs the initializing process will stop and an error will be thrown. The stage will be blocked with a message.

The error message can be modified in the system wide setting messages.STAGE.ERROR_INIT.

Note: In case that the error occurs during the system initialization, the parent System will catch the and handle this error. Please read the chapter "Error Handling" in the documentation of System for furher informations.

Start Definition Object

The stage start definition object stageStart is not optional. It have to be an object and can have the following properties:

id [ String ] (Default: Random String)

Set an id for this stage to access the instance later on via stages getter of a System component. If not set a random id will be assigned.

type [ String ] (Default: "stage")

Type can have the following values:

  • stage: The stage defined in stage is a plain JavaScript object.
  • vue or vue-sr: The stage defined in stage is a Vue Application object that have a single root template.
  • vue-mr: The stage defined in stage is a Vue application object that have a multi root template.
stage [ Stage | Vue ] (Mandatory)

The stage class or Vue application that have to be used.

options [ Object ] (Default: undefined)

The options for the stage.

settings [ Object ] (Default: undefined)

Override here the system wide settings for this stage and all child components.

► Read more about system wide settings

on [ Object ] (Default: undefined)

Early bind callbacks to events. In some cases the application fires events within the initialization phase. Instead of using instance.on("eventname",callback) after initialization (what would be too late) you can define here callbacks which will be early binded to be able to react to this events.

Define just an object with the eventnames as properties and callback functions as values:

1
2
3
on: {
  eventname: callback
}

Implement a Stage

Basics

You can write a new stage as plain JavaScript class or as a Vue application.

To write a new stage class you have to extend the CodeCoupler class Stage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import { Stage } from "@codecoupler/cc-ui";
export default class extends Stage {
  async init() {
    //Mandatory
    //Init process here
  }
  async start() {
    //Optional
    //Will be executed after the "next stage" was initialized
  }
}

The only method you have to provide is async init().

To write a Vue based stage, just write an Vue application which receives the following props:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<template>
  <!-- Put your Template here -->
</template>
<script>
export default {
  props: {
    component: { type: Object, default: null },
  },
};
</script>
<style lang="postcss" scoped>
/* Put your Stylesheet here */
</style>

The property component is a pointer to a base instance of a Stage class. From there you can access all methods and properties of a component like you were writing a plain JavaScript class and would access over this.

Initialization and Starting Process

flowchart TB

  subgraph S1 [ ]
    S1A[Init Container<br>See 'DOM Layout'] --> S1C
    S1C[Block Stage]
  end

  S1C --> A
  A[Execute `init` Method] --> S2AA
  style A color:#000,fill:#ffc929,stroke:#333,stroke-width:4px

  subgraph S2 [ ]
    S2AA[Init Next Stage] --> S2E
    S2E[Unblock Stage]
  end

  S2E --> G
  G[Execute `start` Method] --> I
  style G color:#000,fill:#ffc929,stroke:#333,stroke-width:4px

  I[Stage is initialized]

DOM Layout

Initially, a new div is created in the current stage. This inner div will take 100% of the width and height of the current stage and its position will be set to relative. This is your elemnt in which you can start build your interface.

┌───────────────────────────────────────────────────────────────────┐
│  Previous Stage (container)                                       │
│  Accessible over this.env.start.stage.element                     │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │  div (element)                                              │  │
│  |  Accessible over this.env.element                           │  |
│  │                                                             │  │
│  │  height: 100%                                               │  │
│  │  width: 100%                                                │  │
│  │  overflow: hidden                                           │  │
│  │  position: relative                                         │  │
│  └─────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────┘

In addition to the JavaScript-based widget, you can also create a Vue-based widget. In this case you have to provide a Vue application which will be instantiated.

You have to specify if the Vue application use a single root template or not. Depending on this the inner div described above is the root element (this.$el) of your vue application or just a parent container:

Single root Vue application:

┌───────────────────────────────────────────────────────────────────┐
│  Previous Stage (container)                                       │
│  Accessible over this.componment.env.start.stage.element          │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │  Root element of your Vue template (element)                │  │
│  |  Accessible over this.component.env.element                 │  |
│  │                                                             │  │
│  │  height: 100%                                               │  │
│  │  width: 100%                                                │  │
│  │  overflow: hidden                                           │  │
│  │  position: relative                                         │  │
│  └─────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────┘

Vue with single root template

The variable this.component.env.element where you get normally the root element will not be available while mounting (and thus in the methods beforeCreate, created, beforeMount and mounted).

Multiple root Vue application:

┌───────────────────────────────────────────────────────────────────┐
│  Previous Stage (container)                                       │
│  Accessible over this.componment.env.start.stage.element          │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │  div (element)                                              │  │
│  |  Accessible over this.componment.env.element                │  |
│  │                                                             │  │
│  │  height: 100%                                               │  │
│  │  width: 100%                                                │  │
│  │  overflow: hidden                                           │  │
│  │  position: relative                                         │  │
│  │                                                             │  │
│  │  Multiple root elements of your Vue template:               │  │
│  │  ┌───────────────────────────────────────────────────────┐  │  │
│  │  │                                                       │  │  │
│  │  └───────────────────────────────────────────────────────┘  │  │
│  │  ┌───────────────────────────────────────────────────────┐  │  │
│  │  │                                                       │  │  │
│  │  └───────────────────────────────────────────────────────┘  │  │
│  │  ┌───────────────────────────────────────────────────────┐  │  │
│  │  │                                                       │  │  │
│  │  └───────────────────────────────────────────────────────┘  │  │
│  └─────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────┘

When you finish your implementation and provide the new stage, this will get some style attributes:

┌─────────────────────────────────────────────────────────────────────────┐
│  previous stage (container)                                             │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  You Stage (element)                                              │  │
│  |  ┌─────────────────────────────────────────────────────────────┐  │  │
│  │  │  New Stage Provided                                         │  │  │
│  │  │                                                             │  │  │
│  │  │  position: absolute | relative | fixed (Default: relative)  │  │  │
│  │  │  isolation: isolate                                         │  │  │
│  │  │  overflow: hidden                                           │  │  │
│  │  └─────────────────────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────┘

What's next

Within your init function you can manipulate the element which is accessible over this.env.element (or this.component.env.element in a Vue application) however you need.

You could even replace the element with a new div (or any other block element), since the styles of the element described above are set by the parent container.

As soon as the initialization is done by your init function or the Vue application is created, the resulting structure you have created will be inspected.

The structure you have built has to meet only one requirement. You have to provide a container that will act as a new stage from now on. The new stage container element must have set the attribute data-role="cc-stage". If this requirement is not met, an error will be thrown.

Reference

In addition to the common instance members described in the base class Component a stage has the following:

Instance Properties

vue and vueApp

This properties will be accessible if the stage is Vue based. vue points to the Vue instance and vueApp to the Vue application object.

Instance Getter

$nextStage

Next stage defined by the instance as jQuery object.

Reserved Names

The following members are used for internal purposes and must not be overridden:

  • static $setStageStyles(stage)