Skip to content

Switch to Vue

Now that we know how to create a system with applications, let us rewrite some of the components as a Vue application. This can be done for a Stage and a Widget.

Stages as Vue Application

Let's start with our header stage and rewrite the functionality as Vue application:

stage/header.vue

 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
<template>
  <div class="header-stage d-flex flex-column h-100">
    <div class="header text-white">
      Header as Vue with option: {{ options.header }}
    </div>
    <div class="flex-grow-1 position-relative" data-role="cc-stage"></div>
  </div>
</template>
<script>
export default {
  props: {
    env: { type: Object, default: null },
    options: { type: Object, default: null }
  }
};
</script>
<style lang="postcss" scoped>
.header-stage {
  & .header {
    background-color: var(--color-primary-2);
    min-height: 40px;
    padding: 10px;
  }
}
</style>

lang=postcss

As you can see the attribute lang=postcss was set in the <script> section. This was done to make the syntax highlighting and formatting of Visual Code and Vetur work together.

Now we replace in our index.js the module we import and add only a property type: "vue" into the stage definition:

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
import { System, Sidebar } from "@codecoupler/cc-ui";
import HeaderStage from "./stages/header.vue";
import apps from "./apps.js";
import "./style.css";
import "./sidebar.css";
let system = new System({
  id: "codecoupler-walkthrough",
  apps: apps,
  stages: [
    {
      stage: Sidebar,
      options: { logo: "logo.png" }
    },
    {
      type: "vue",
      stage: HeaderStage,
      options: { header: "Test" }
    }
  ],
  panel: {
    setStatus: "maximized",
    header: false
  }
});
system.initialized.then(() => {
  console.info("System is Ready!");
});

The header is now a Vue application. The files stage/header.html, stage/header.css and stage/header.js are not needed anymore.

The Vue application receives the arguments env and options now as props:

As plain JS As Vue
async init(env, options) {} props: { env: { ... }, options: { ... } }

The argument env has one more property named stage which points to the stage instance as it would be if the stage is written in plain JavaScript.

Single root and Multiple roots

As of Vue 3 you are not limited to a single root element in the template anymore. This is an extremely useful feature but within the CodeCoupler system you have to pay attention to the following:

If you are using a single root template you have to set the type to vue or vue-sr.

If you are using multiple root elements you have to set the type to vue-mr.

Widgets as Vue Application

Now let's rewrite one of our widgets as a Vue application:

widgets/testing-visibility.vue

 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
<template>
  <div>
    <h1>Visibility Testing <span>Vue</span> Widget!</h1>
    <p>Text: {{ options.text }}</p>
  </div>
</template>
<script>
export default {
  props: {
    env: { type: Object, default: null },
    options: { type: Object, default: null }
  },
  mounted: function () {
    //Bind to an own event "visibilitychanged".
    this.env.widget.on("visibilitychanged", () => {
      console.info(
        `${this.options.text}: fullvisible is ${this.env.widget.fullvisible}`
      );
    });
    console.info(
      `${this.options.text}: fullvisible is ${this.env.widget.fullvisible}`
    );
  }
};
</script>
<style lang="postcss" scoped>
h1 {
  color: red;
  & span {
    color: green;
  }
}
</style>

lang=postcss

As you can see the attribute lang=postcss was set in the <script> section. This was done to make the syntax highlighting and formatting of Visual Code and Vetur work together.

Now we replace in our application that uses this widget the module we import, the property type inside the widget definition and switch from the property widget to vue:

apps/testing-buttons.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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { Application, Layout } from "@codecoupler/cc-ui";
import buttons from "./custom-buttons";
import MyFirstWidget from "../widgets/my-first-widget.js";
import TestingSizingWidget from "../widgets/testing-sizing";
import TestingVisibilityWidget from "../widgets/testing-visibility.vue";
export default class extends Application {
  static ui = {
    name: "Testing Buttons",
    iconHtml: '<i class="fas fa-seedling fa-fw"></i>'
  };
  async init() {
    let layout = {
      header: {
        show: true
      },
      root: {
        type: "row",
        content: [
          {
            type: "widget",
            title: "Number 1",
            widget: TestingSizingWidget,
            options: {
              text: "Hallo Everyone"
            }
          },
          {
            type: "column",
            content: [
              {
                type: "widget",
                title: "Number 2",
                widget: MyFirstWidget,
                options: {
                  text: "How are you?"
                }
              },
              {
                type: "stack",
                content: [
                  {
                    type: "widget",
                    title: "Number 3",
                    widget: MyFirstWidget,
                    options: {
                      text: "I'm fine, thanks!"
                    }
                  },
                  {
                    type: "vue",
                    title: "Number 4",
                    vue: TestingVisibilityWidget,
                    options: {
                      text: "Widget Number 4"
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    };
    await super.init({
      panel: {
        panelSize: "820 600",
        headerTitle: "My First Title",
        footerToolbar:
          '<i class="far fa-hand-point-right mx-1"></i> [inline][blocks][hints][alerts][close]'
      },
      buttons: buttons,
      widget: {
        widget: Layout,
        options: layout
      }
    });
  }
}

The widget is now a Vue application. The file widgets/testing-visibility.jsis not needed anymore.

The Vue application receives the arguments env and options now as props:

As plain JS As Vue
async init(env, options) {} props: { env: { ... }, options: { ... } }

The argument env has one more property named widget which points to a widget instance as it would be if the widget is written in plain JavaScript.

Single root and Multiple roots

As of Vue 3 you are not limited to a single root element in the template anymore. This is an extremely useful feature but within the CodeCoupler system you have to pay attention to the following:

If you are using a single root template you have to set the type to vue or vue-sr.

If you are using multiple root elements you have to set the type to vue-mr.