8. Script Block - Introduction
In this chapter, we will create a Note widget. It is a relatively simple widget to build, but we need to address a few challenges to ensure it functions correctly as a WEM widget.
As mentioned previously, adding widgets will introduce CSS and JavaScript into a global space. This can be quite challenging for more advanced widgets, as we want to avoid overriding and breaking existing CSS and JavaScript. Therefore, we will start with some scaffolding to see how we can prevent these issues.
We will learn about invariant culture, naming collisions, cleaning up the widget, and a few other concepts along the way. Let's get started!
Create a new widget and name it "Note."
Copy and paste the following CSS into a new file called "note.css."
Add it as a resource named "NoteCss."
Notice that we use a more specific class name for our Note widget, .wem-note
.
Copy and paste the JavaScript code below into a new file called "note.js."
Add it as a resource named "NoteJs."
The above CSS and JavaScript code are standalone and can even be used in a non-WEM application if desired. The code below is necessary to make it work as a WEM widget. There are a few interesting aspects that we will dissect later.
Invariant Culture
An extra argument, invariant culture
, has been added to the register input
statements in the following lines of code:
In the previous encoding section, I explained the different writing formats used by various cultures (for example, in English, a "." is used as a decimal separator, while in Dutch, a "," is used). This discrepancy can make it challenging for programmers to read and write numbers consistently between systems. An "invariant culture" is essentially an artificial culture where the format specifications remain constant. In the case of numbers, the "invariant culture" specifies that the decimal separator will be a ".".
ID Attribute
In addition to the name
attribute we encountered in our Simple Form widget, we have now added an id
attribute to the <input>
elements in the following lines of code:
The reason we need the id
attribute here is that we have an additional step in the submitscript
to retrieve the new values from the note instance, and we want to write those values back to these inputs. The name
attributes are still mandatory on the <input>
fields for sending the data back with the request to the WEM runtime.
Special Script Blocks
You may have noticed that we haven't written any JavaScript inside a <script>
tag yet. This is not incorrect by any means, and there are situations where it is even necessary when using third-party libraries. However, when building a widget, you want to have more control over when to call functionality in response to specific events. Each piece of JavaScript code in these special JavaScript blocks can be thought of as handlers, similar to a click handler on a button. We have three special JavaScript blocks; let's walk through them.
Startup Script
This code will run after the page has been fully replaced, making it ideal for initializing JavaScript instances since you can be sure that all elements have been rendered. As shown in the example above, we initialize our note here. You may be wondering about the Symbol.for
statement; I will explain that later.
Submit Script
This code executes after an event has been triggered, such as a button click, but before the request is made. It is ideal for sanitizing and serializing data, as well as updating the data just before sending it with the request. This is why we need the id
attribute on the input fields.
Unload Script
The code above runs after receiving a new response from the server but before the new page is rendered. It is perfect for cleaning up a widget instance. In this case, we call the note.dispose()
method to clean up our Note widget. It is always important to perform cleanup, especially when there may still be a callback from setTimeout()
that needs to be cleared with clearTimeout()
. Additionally, our Note widget could still have "mouseup"
and "mousemove"
event listeners attached to the window
object. Although optional, deleting the note ensures that there are no lingering references in the JavaScript runtime, which can assist the garbage collector.
Conclusion
We have built the foundational components to initialize our widget via the startupscript
, update our form data using the submitscript
, and clean up our widget in the unloadscript
. To reduce the risk of naming collisions, we prefixed our class names to make them less generic. In the next chapters, we will explore additional details, such as the purpose of window[Symbol.for(<?js OutputId() ?>)]
in the code above.
Last updated
Was this helpful?