Special Levels: Error Messages
What are we learning here?
- How to block a stage with an error message
- Using the helper method
block(Type, Message)
Now let's look at the layer error
. This layer is also a blocking layer like block
and have a
higher z-index as as block
. It's semi-transparent background is redder.
Here is another special feature of blocking layers. All blocking layers hide all underlying blocking
layers, of course including all components loaded there. As soon as these are no longer used, they
are removed and the highest underlying blocking layer is shown again. So there is always only one
blocking layer to see.
The code of loading an error message manually in contrast to the code of loading an normal message
is almost identical. The only difference would be the option level
which value is in the one case
block
and in the other error
.
We will use now a shortcut which is available for every component this.block(type,text,id)
and
unblock(id)
. type
can be info
or error
. info
will load the message into the level block
like in the chapter before.
The shortcut will load the component Message
into the level block
like in the chapter
before (setting type to info
) or error
(setting type to error
) of the root stage.
Why using the shortcuts
The shortcut takes into account a few important points in cases where an application block and
unblock a component especially if you have many parallel tasks which blocks and unblocks a
component in a unpredictible manner.
The shortcut takes care of blocking the root stage and if not possible the stage of the component.
This is important in cases where a hint should be given before a component is initialized. The
shortcut remembers the stage in which the block was applied in order to destroy it correctly.
And finally the function tries to avoid race conditions between block and unblock:
- Multiple parallel loads will be handled correctly.
- Multiple parallel destroying and destroying of components that are not yet initialized will be
handled correctly.
Let's add one button into our HTML structure:
src/demo/components/loading-components/index.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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 | <div class="border rounded d-inline-block p-1 mr-2 my-1 bg-white text-dark">
Block
<button class="btn btn-xs btn-info" data-role="blockMessage">
<i style="pointer-events: none" class="fas fa-check-circle"></i>
</button>
<button class="btn btn-xs btn-danger" data-role="blockError">
<i style="pointer-events: none" class="fas fa-exclamation-circle"></i>
</button>
</div>
<div class="border rounded d-inline-block p-1 mr-2 my-1 bg-white text-dark">
Modal
<button class="btn btn-xs btn-info" data-role="modalApp">
<i style="pointer-events: none" class="fas fa-check-circle"></i>
</button>
<button class="btn btn-xs btn-info" data-role="modalMultiApp">
<i style="pointer-events: none" class="fas fa-play-circle"></i>
</button>
</div>
<div class="border rounded d-inline-block p-1 mr-2 my-1 bg-white text-dark">
Hint
<button class="btn btn-xs btn-info" data-role="hintInfo">
<i style="pointer-events: none" class="fas fa-info-circle"></i>
</button>
<button class="btn btn-xs btn-success" data-role="hintSuccess">
<i style="pointer-events: none" class="fas fa-check-circle"></i>
</button>
<button class="btn btn-xs btn-danger" data-role="hintError">
<i style="pointer-events: none" class="fas fa-exclamation-circle"></i>
</button>
</div>
<div class="border rounded d-inline-block p-1 mr-2 my-1 bg-white text-dark">
Note
<button class="btn btn-xs btn-info" data-role="hintInfoP">
<i style="pointer-events: none" class="fas fa-info-circle"></i>
</button>
<button class="btn btn-xs btn-success" data-role="hintSuccessP">
<i style="pointer-events: none" class="fas fa-check-circle"></i>
</button>
<button class="btn btn-xs btn-danger" data-role="hintErrorP">
<i style="pointer-events: none" class="fas fa-exclamation-circle"></i>
</button>
</div>
<div class="border rounded d-inline-block p-1 mr-2 my-1 bg-white text-dark">
Splash
<button class="btn btn-xs btn-info" data-role="hintSplash">
<i style="pointer-events: none" class="fas fa-exclamation-circle"></i>
</button>
</div>
<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>
|
And add a handler:
src/demo/components/loading-components/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
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 | import { Canvas, Hint, Message } from "@codecoupler/cc-ui";
import Mockup from "../../apps/mockup";
import { toRaw } from "vue";
import template from "./index.html";
import modalMultiApp from "./modal-multi-app";
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;
}
async blockError() {
await this.target.block("info", "Normal Message", "A");
await new Promise((r) => setTimeout(() => r(), 2000));
await this.target.block("error", "Error Message", "B");
await new Promise((r) => setTimeout(() => r(), 2000));
this.target.unblock("B");
await new Promise((r) => setTimeout(() => r(), 2000));
this.target.unblock("A");
}
async blockMessage() {
let message = await this.target.getStage("root").load({
component: Message,
options: { text: "You are blocked!" },
level: "block"
});
for (let x = 0; x <= 100; x += 25) {
await new Promise((r) => setTimeout(() => r(), 750));
message.text = `Please Wait\n${x}% Progress`;
}
await new Promise((r) => setTimeout(() => r(), 2000));
message.destroy();
}
modalMultiApp() {
modalMultiApp(this.target, Mockup);
}
modalApp() {
this.target.getStage("root").load({ component: Mockup, level: "block" });
}
hintInfo() {
this.target.getStage("root").load(Hint, { type: "info", text: "Hint!" });
}
hintSuccess() {
this.target.hint("success", "Hint!");
}
hintError() {
this.target.hint("error", "Hint!");
}
hintInfoP() {
this.target.hint("info-permanent", "Permanent Hint!");
}
hintSuccessP() {
this.target.hint("success-permanent", "Permanent Hint!");
}
hintErrorP() {
this.target.hint("error-permanent", "Permanent Hint!");
}
async hintSplash() {
let splash = await this.target.hint("splash", "Splash!");
for (let x = 0; x <= 100; x += 25) {
await new Promise((r) => setTimeout(() => r(), 750));
splash.text = `Please Wait\n${x}% Progress`;
}
await new Promise((r) => setTimeout(() => r(), 2000));
splash.destroy();
}
appNoId() {
this.target.stage.load(Mockup);
}
appId() {
this.target.stage.load(Mockup, "fixed-id");
}
}
|
Now click on the new button to start the show:
- A normal message will be loaded into the layer
block
. As a result, the widget will be blocked.
- After 2 seconds an error message will be loaded into the layer
error
. As a result, the layer
block
will be hidden.
- After 2 seconds the error message component will be destroyed. As a result, the layer
block
appears again.
- After 2 seconds the normal message component will be destroyed. As a result, the widget will be
unblocked.