To add custom JavaScript to a widget you must create a JavaScript file under the <WIDGET NAME>/js directory.
Custom JavaScript for a widget assumes that the file specified by the JavaScript property will perform some custom logic and return an object with extensions to the widgetViewModel. The JavaScript file expected should implement the following format using RequireJS. See http://requirejs.org/docs/api.HTML#defdep.
Note: The module must be defined anonymously, as shown below.
define( // Dependencies ['jquery', 'knockout'], // Module Implementation function(ko) { // We recommend enabling strict checking mode 'use strict'; // Private variables and functions can be defined here... var SOME_CONSTANT = 1024; var privateMethod = function () { // ... }; return { // Widget JS // Some member variables... textInput: ko.observable(), // Some public methods... doSomethingWithInput: function () { //... } } });
The define statement above can be modified to include widget-specific libraries or other JavaScript files, if required. When a widget is instantiated all properties returned from the JavaScript file specified will be copied into that instance of the WidgetViewModel. This allows you to define properties, make Web API calls, or handle UI events.
OnLoad()
If you must run custom logic when the widget is instantiated then add an ‘onLoad’ function to the widget JavaScript’s return object:
onLoad: function(widget) {
//onLoad code here.
}
onLoad will run once the widget has finished loading and is populated with the necessary data. This is the main access point to configure data for the widget after its properties have been loaded and the system is ready to display the widget. As the onLoad function is only called the first time the widget is instantiated, when returning to the same “page”, the widget does not need to be re-instantiated, so onLoad is not called again..
BeforeAppear()
If you require some logic to run each time the widget appears on the page, add the ‘beforeAppear’ function to the widget JavaScript’s return object:
beforeAppear: function(page) {
// Code to run before showing the widget here.
}
beforeAppear is run once any re-population of mapping data has occurred. This can be useful when a Web API call is required every time the widget is shown, or, some other functionality required every time the widget is shown.
OnRender()
OnRender is a hook you can use within a binding to specify a function to run when an element is being rendered.
The function is called in the current knockout context (typically bound to the widget, but certain knockout constructs, such as for each, may alter the binding context). For example:
<div id="CC-customerProfile" data-bind="onRender: addEventHandlersForAnchorClick">
<!-- ... -->
</div>
Rely on mapping for a property vs. initializing it via JavaScript
Most of a custom widget’s data will come from the JSON. This data does not need to be explicitly defined in the WidgetViewModel; knockout mapping will automatically create it.
For any data that doesn’t come through JSON, the binding should be explicitly defined in custom JavaScript. Otherwise, an error will be thrown if a template tries to render the property while it’s undefined. For example, imagine a productName widget that is configured with a productId and uses that productId to lookup a product to display its name. In this case the productId can be a property defined via koMapping as it should be returned by the JSON data. The product’s name on the other hand is expected to be populated when the product lookup completes so it needs to be defined in JavaScript as productName: ko.observable(). Otherwise, when the template is rendered an error will be thrown because productName is not a valid binding (it would be undefined).
This and Self
Using ‘this’ in the custom JavaScript is suitable when you refer to the widget itself, but be careful of any callback methods where ‘this’ may refer to a different context.
Include multiple JavaScript files
If your widget requires multiple JavaScript files then any additional JavaScript files can be loaded through the dependencies in your module’s define statement.
To derive the path of the dependency, you should use the relative path of ‘./’ to reference the Widget’s JavaScript folder, followed by the path to the dependency but omitting the ‘.js’ extension.