This article was written by Anand Yerrapati from the Oracle Cloud Solution Engineering team.
Visual Builder provides multiple level of reusability in the UI layer, including application and page templates, reusable page fragment, and reusable action chains. This article explains how to create a reusable custom component that you can add to multiple pages in your applications. Our sample component consists of an input text with action buttons Cancel and Accept.
Create a custom component
Start by creating a new web application. Then to create e new component:
- Open application structure under web apps
- Expand Resources
- Right-click on the “components” folder and select Create option
- Enter an id value for the custom component in the input text field on the dialog opened (we used custom-input-text in our sample component)
- Click on Create button
- This step will create a folder with a set of files as shown below
- Here is an explanation of each of these files
- loader.js: This file helps to register the custom component with the application. So that, it can be used on any page in the application just like any other common components
- component.json: This file helps to configure the parameters, methods, and events used in the custom component and exposed outside of the component
- <name>-view.html: This file defines the view of the component which will be the face of the custom component
- <name>-viewModel.js: This file handles the logic for the components in the view
- <name>-style.css: This file styles the custom components with the CSS
Building the custom component
Our goal in this article is to create a custom component that shows text with an edit icon and allows in-place editing as shown below.
- Open the component.json file
- Add the below properties required for the custom component
"properties": {
"hintText" : {
"type" : "string"
},
"inputText" : {
"type" : "string"
}
}
- Add the below custom event to trigger back when there is a change in the text
"events": {
"inputTextChanged" : {
"description" : "The event for on click check (ok) button",
"bubbles" : true,
"cancelable" : false,
"detail" : {
"newText" : {"type" : "string"}
}
}
}
- After making these changes the component.json will look like as below
{
"name": "custom-input-text",
"displayName": "custom-input-text",
"description": "A description of custom-input-text.",
"version": "1.0.0",
"jetVersion": ">= 9.0.0",
"properties": {
"hintText" : {
"type" : "string"
},
"inputText" : {
"type" : "string"
}
},
"methods": {},
"events": {
"inputTextChanged" : {
"description" : "The event for on click check (ok) button",
"bubbles" : true,
"cancelable" : false,
"detail" : {
"newText" : {"type" : "string"}
}
}
},
"slots": {}
}
Open custom-input-text-view.html file and add the below HTML code
<div>
<oj-bind-if test="[[!editMode()]]">
<oj-bind-text value="[[inputText]]"></oj-bind-text>
<oj-button chroming="borderless" id="btEdit" display="icons" on-oj-action="[[ onEditClick ]]">
<span class="oj-ux-ico-edit" slot="startIcon"></span>
</oj-button>
</oj-bind-if>
<oj-bind-if test="[[editMode()]]">
<div class="oj-flex">
<oj-input-text value="{{ $properties.inputText }}" placeholder="[[$properties.hintText]]" style="width: 200px;"></oj-input-text>
<oj-button chroming="borderless" id="btCancel" display="icons" on-oj-action="[[ onCloseClick ]]">
<span class="oj-ux-ico-close" slot="startIcon"></span>
</oj-button>
<oj-button chroming="borderless" id="btSubmit" display="icons" on-oj-action="[[ onCheckClick ]]">
<span class="oj-ux-ico-check" slot="startIcon"></span>
</oj-button>
</div>
</oj-bind-if>
</div>
Open custom-input-text-viewModel.js file and replace the code with the below
define([
'knockout',
'ojs/ojcontext',
"ojs/ojinputtext"
], (
ko,
ojContext
) => {
'use strict';
class CustomInputTextComponentModel {
constructor(context) {
// At the start of your viewModel constructor.
var busyContext = ojContext.getContext(context.element).getBusyContext();
var options = { 'description': 'Component Startup - Waiting for data' };
var self = this;
self.busyResolve = busyContext.addBusyState(options);
self.composite = context.element;
self.properties = context.properties;
self.editMode = ko.observable(false);
// Example observable.
self.inputText = ko.observable(self.properties.inputText);
// Once all startup and async activities have finished, relocate if there are any async activities.
self.busyResolve();
self.onEditClick = (event) => {
self.composite.addEventListener('ojAction', function (event) {
if (event.srcElement.id === "btCancel")
self.onCloseClick(event);
else if (event.srcElement.id === "btSubmit")
self.onCheckClick(event);
});
self.editMode(true);
};
self.onCloseClick = (event) => {
self.editMode(false);
};
self.onCheckClick = (event) => {
if (self.editMode()) {
var eventParams = {
'bubbles': true,
'cancelable': false,
'detail': {
'newText': self.inputText()
}
};
//Raise the custom event
self.composite.dispatchEvent(new CustomEvent('inputTextChanged', eventParams));
self.editMode(false);
}
};
}
}//End of the class CustomInputTextComponentModel
return CustomInputTextComponentModel;
});
Your custom component is ready.
How to use the custom component
- Open the main page of the application
- Under Components, search for the “custom-input-text”
- Drag & Drop the components from the search result to the code editor
- Fill in the properties below
- hint-text : "Hello Text"
- input-text: "[[ $variables.mytext ]]" — (mytext is a string variable)
- Create an event for "on-input-text-changed"
- Go to the action chain created for the event
- Drag & Drop “Fire Notification” components on the design
- Enter [[ $variables.newValue.newText ]] for summary and select Notification Type as “info”
- Now the application is ready to run to test the custom component
Explanation of the custom component Behavior
So far, we have seen how to create and use the custom component. In this section, we will understand what happens in the flow.
- When the application is run, the component will display the given text (value of “input-text” property) with an edit icon.
- On click of the edit icon, it will show an input text component filled with the given text and two buttons Cancel and Accept
- On click of the Cancel button (X), it will close the current view of the input text and displays the previous text with the edit icon
- On click of Accept button (✓), it will trigger a custom event (on-input-text-changed) with the new text and it will close the current view of the input text and displays the new text with the edit icon.
- When we create an event listener for the component, the new text will be passed to the corresponding action chain
- In this example, we are showing that text on a notification
How to import a custom component
While we created the custom component directly in an app, you can also create components outside of Visual Builder creating the same directory and files that we created above. You can then zip the directory to create a zip file that other developers can add to their application to use your component. To import a custom component:
- Expand the application structure in VBCS
- Under Resources, right-click on components
- Select the Import option
- Upload the zip file of the custom component
- Click on the Import button
- You will be able to see the folder structure below for the custom component
Conclusion
As you can see creating reusable custom components is quite simple. This can help you extend the functionality your development team can create in their user interfaces beyond the set of components provided out of the box by Visual Builder. To learn more on creating custom components check out Duncan's custom components learning path series of blog entries.
