# Extensible Components and Usage Guide
This document provides detailed information and usage guide for extensible components, listing the methods to extend extensible components and helping developers understand and use the custom features of components better. In the following document, we will first introduce the concept of extensible components and the methods to extend them using Component API and Fragment configuration. Then, we will provide a detailed list of extensible components, so that developers can have a clear understanding of which components can be modified.
# Prerequisites
To better understand this document, you may need to be familiar with the following concepts:
- For Fragment configuration: please refer to UI Fragments section.
- For Appearance usage: please refer to Appearance section.
- For layout templates: please refer to Layout Template section.
- For component selector syntax: please refer to Component Selector section.
- For Component API: please refer to the API Reference (opens new window).
- For the
@controller
directive: please refer to the @controller directive section. - For the
@tooltip
directive: please refer to the @tooltip directive section. - For the
@on
directive: please refer to the @on directive section.
The upcoming content will utilize the knowledge mentioned above. Please familiarize yourself with them before reading this document, as they will not be repeated here.
# Overview of Extensible Components
- What are extensible components: Components that can be customized and extended in terms of functionality and appearance through Fragment configuration or Component API.
- What are non-extensible components: The opposite of extensible components, which cannot be modified. These components are deeply encapsulated within the SDK, so they cannot be broken down and combined at a granular level. However, some of them can be replaced as a whole (e.g., Annotation Property Dialog). More specific details will be provided in subsequent sections.
- Note: Some components do not have unique name identifiers, so they cannot be directly targeted by name. In such cases, component selector syntax can be used.
# Extensible Components
# Header Area
# Tab Component
The tab component is wrapped in a div container named toolbar-tabs
, while the tab panel is wrapped in a div container named toolbar-tab-bodies
. If you want to add or remove tabs, you need to modify both of these containers. Here is an example (click the run
button to see the effect):
Add a tab at the end
In this example, we inserted a new tab called
custom-tab
at the end of the tab bar, and also inserted a div component calledfv--custom-tab-body
.Remove a specific tab
In this example, we remove both the
edit-tab
andfv--edit-tab-paddle
components, and then theedit
tab will not be visible in the view.Replace a specific tab
In this example, the
edit-tab
tab is replaced with a custom tab.Insert a tab at a specified position
The following example inserts a custom tab after a specified position. Similarly, there is a
FRAGMENT_ACTION.BEFORE
operation, which means that the component is inserted before the specified target component.Use Component API
The following example uses selector syntax and the
Component.after
method to insert more tab components into the page.Compared to editing components with the Fragment configuration, which can only be done during initialization, using the Component API allows you to dynamically edit components at any time after PDFUI initialization.
# Tab Panel Components
The tab panel component is the panel displayed after selecting a tab. Currently, the default layout template used by the SDK uses the paddle
component as the tab panel component. The purpose of using this component is to display buttons on the left and right sides when the browser view width is small, which can be used to scroll the components within the panel.
The paddle component can be seen as a normal ContainerComponent
. You can use the Fragment configuration to insert child components into it using the FRAGMENT_ACTION.APPEND
operation, or you can use the Component API to insert child components. The following examples will illustrate this.
Insert components using the Fragment Configuration
This example uses the Fragment configuration to insert a hand button into the paddle component by default.
Insert components using the Component API
This example uses the Component API to insert a hand button. The effect will be the same as the previous example.
In the default layout template, we use the group-list
component to group the child components within the paddle
component. In practice, it is more common to edit the group-list
component. The following example will use group-list
and group
to illustrate:
In this example, we insert a new custom-group
where the group contains two hand button components, and set it to only display one component when collapsed.
# Button Components in Tab Panels (ribbon-button)
The ribbon-button
is a powerful component that can be used as a regular button or as a dropdown component. Let's first explore the custom methods for using ribbon-button as a regular button.
As a regular button, the ribbon-button
component can be customized with the following:
Text Content: the text displayed on the button.
Icon: the button icon, specified through the
icon-class
attribute, which requires additional CSS styles.Tooltips: the floating tooltip content displayed when the mouse hovers over the button, implemented through the
@tooltip
directive andtooltip-title
attribute.Controller: usually used for business implementation, and generally used to reuse internal SDK implementation logic on custom buttons.
The following is an example of a custom button that reuses business logic using the SDK's built-in controller:
From this example, we can see that when reusing a controller, the @controller=""
directive can be used to specify the Controller
that needs to be reused. Apart from states:HandController
, there are many other controllers that can be reused. For more details, please refer to the Controllers section.
In addition to reusing logic with custom buttons, you can also directly modify the built-in components of the SDK. The main way to do this is through configuring Fragments. For example, the following example fully demonstrates how to customize the content of the hand-tool
(ribbon-button):
# Dropdown Components in the Toolbar Tab Panel
On the toolbar, the dropdown
component is usually used in conjunction with the ribbon-button
component. However, you can also use it separately. The only difference between these two usage methods is the display effect. The following is an example of using ribbon-button
and dropdown
together:
For more business components, you can refer to the pre-configured components section. This section describes the default configurations of multiple business components, and we can adjust them using Fragment configuration based on these configuration options.
# Left Panel
In the default layout, the left panel is constructed using the sidebar
component, and its child components correspond to different business modules encapsulated in the sidebar-panel
component.
In this section, we will learn about some customization methods and details of the left panel.
# Create a sidebar-panel
Here is a template for the sidebar-panel
component that includes basic properties:
<sidebar-panel
class="custom-sidebar-panel"
icon-class="custom-sidebar-icon"
title="Custom"
>
</sidebar-panel>
If needed, you can add directives to it, such as the @tooltip
directive:
<sidebar-panel
class="custom-sidebar-panel"
icon-class="custom-sidebar-icon"
title="Custom"
@tooltip
tooltip-placement="right"
tooltip-title="Custom Sidebar"
>
</sidebar-panel>
If you need to listen to the active
event (when the sidebar-panel is expanded), you can use the @on.active
directive to listen to it. Please refer to the following example:
class CustomSidebarPanel extends SeniorComponentFactory.createSuperClass({
template: `
<sidebar-panel
class="custom-sidebar-panel"
icon-class="custom-sidebar-icon"
title="Custom"
@tooltip
tooltip-placement="right"
tooltip-title="Custom Sidebar"
@on.active="$component.handleActiveEvent()"
>
</sidebar-panel>
`
}) {
static getName() {
return 'custom-sidebar-panel'
}
handleActiveEvent(){
console.log('hello world')
}
}
Finally, let's take a look at a runnable example:
# Delete a sidebar-panel
If you want to delete the built-in sidebar-panel
component in the SDK, we recommend using Fragment configuration instead of the Component API to delete it, unless it is necessary. This is because initializing a sidebar-panel
component may require a significant amount of resources, and deleting it through Fragment configuration can avoid unnecessary initialization.
{
target: '@layer-sidebar-panel',
action: UIExtension.UIConsts.FRAGMENT_ACTION.REMOVE
}
# Customize the internal components of the built-in sidebar-panel
in the SDK
# 1. commentlist-sidebar-panel
In the commentlist sidebar panel, the CommentCardComponent and ReplyCardComponent can be customized. However, unlike other components, they are dynamically generated based on the current type and number of comments in the document, and their details cannot be modified through Fragment configuration. But we provide events that allow you to obtain the component objects when they are created or deleted, and then modify the details of these components using the Component API.
Here are the descriptions of the relevant events:
1). UIExtension.UIEvents.appendCommentListComment
: Triggered when the CommentCardComponent component is inserted. The event callback can obtain the commentCardComponent
and annot
parameters.
2). UIExtension.UIEvents.destroyCommentListComment
: Triggered when the CommentCardComponent component is destroyed. The callback parameters are the same as those of the appendCommentListComment
event.
3). UIExtension.UIEvents.appendCommentListReply
: Triggered when the ReplyCardComponent component is inserted. The event callback can obtain the replyCardComponent
and replyAnnot
parameters.
4). UIExtension.UIEvents.destroyCommentListReply
: Triggered when the ReplyCardComponent component is destroyed. The callback parameters are the same as those of the appendCommentListReply
event.
You can refer to the API Reference for usage information:
# 2. thumbnail-sidebar-panel
You can refer to the section: Customize Thumbnail
# 3. bookmark-sidebar-panel
You can refer to the section: Custom Bookmark
# 4. Others
Apart from the three mentioned above, layer-sidebar-panel
, attachment-sidebar-panel
, and field-sidebar-panel
currently do not provide customization capabilities.
# Context Menu
The context menu refers to the component implemented based on ContextMenuComponent
(opens new window). All customizable context menus are implemented based on the same principle:
Each context menu for a specific functionality has a fixed name, and replacing a context menu requires specifying the name. After replacement, the name cannot be changed, as it may cause the context menu to not be displayed or overwrite other context menus, affecting the display of other functionalities.
Context menu items can be added, deleted, and replaced through Fragment configuration and the Component API.
The
contextmenu-separator
separators at the beginning, end, or in a continuous sequence will be automatically hidden and generally do not need to be specifically controlled for showing or hiding.
Next, the context menus for each functional module will be introduced one by one.
# 1. PDF Page Context Menu
Please refer to the section Customizing Page Context Menu.
# 2. Annotation Context Menu
Please refer to the section Customizing Annotation Context Menu.
It should be noted that since the Annotation property dialog does not support customization, when implementing a custom property dialog, the implementation of <contextmenu-item-properties>
needs to be replaced. You can refer to the following example:
# 3. Other Context Menus
Customizing other context menus is similar to the Page context menu and Annotation context menu described above. You can refer to these documents for self-expansion. The templates for relevant menu components can be found in the section Pre-configured Components.
# Modals
If it is a pop-up within the SDK, including alert, prompt, confirm, and loading overlay, we can define these components triggered by the SDK internally through Viewer UI. For specific usage, please refer to the section Viewer UI.
# Controller Reusability
Below is a list utilizing the @controller
directive syntax, enumerating the currently reusable controller implementations within the SDK. Module names are listed before the colon, and controller names are listed after the colon.
# Built-in Controllers in UIExtension
Built-in controllers can be directly accessed using UIExtension.modular.module('module name').getController('controller name')
to retrieve the class.
states:HandController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_HAND
.marquee:MarqueeToolController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_MARQUEE
.loupe:LoupeController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_LOUPE
.states:SnapshotToolController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_SNAPSHOT_TOOL
.file:DownloadFileController
: Used to download the currently open document.zoom:ZoomInAndOutController
: Controls document view zooming, and needs to be used with theaction
attribute. Optional values are:action="zoomin"
andaction="zoomout"
.pagemode:SinglePageModeController
: Switches page mode to single page mode.pagemode:ContinuousPageModeController
: Switches page mode to continuous page mode.pagemode:FacingPageModeController
: Switches page mode to facing page mode.pagemode:ContinuousFacingPageModeController
: Switches page mode to continuous facing page mode.states:CreateTextController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_TEXT
.states:CreateFileAttachmentController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_FILE_ATTACHMENT
.states:CreateHighlightController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_HIGHLIGHT
.states:CreateStrikeoutController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_STRIKE_OUT
.states:CreateUnderlineController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_UNDERLINE
.states:CreateSquigglyController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_SQUIGGLY
.states:CreateReplaceController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_REPLACE
.states:CreateCaretController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_CARET
.states:CreateTypewriterController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_TYPEWRITER
.states:CreateCalloutController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_FREETEXT_CALLOUT
.states:CreateTextboxController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_FREETEXT_BOX
.states:CreateAreaHighlightController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_AREA_HIGHLIGHT
.states:CreatePencilController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.PENCIL
.states:EraserController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_ERASER
.states:CreateLinkController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_LINK
.states:CreateImageController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_IMAGE
.zoom:DropdownZoomInAndOutController
: Same aszoom:ZoomInAndOutController
, but can only be used in dropdown subcomponents.zoom:ZoomActionController
: Controls document view zooming, and is different fromzoom:ZoomInAndOutController
in that it needs to specify the target zoom level (non-numeric):action='fitHeight'
,action='fitWidth'
,action='fitVisible'
.gotoview:GotoFirstPageController
: Jumps to the first page.gotoview:GotoPrevPageController
: Jumps to the previous page.gotoview:GotoNextPageController
: Jumps to the next page.gotoview:GotoLastPageController
: Jumps to the last page.states:CreateSquareController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_SQUARE
.states:CreateCircleController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_CIRCLE
.states:CreatePolygonController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_POLYGON
.states:CreatePolygonCloudController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_POLYGON_CLOUD
.states:CreateArrowController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_ARROW
.states:CreateLineController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_LINE
.states:CreatePolylineController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_POLYLINE
.distance:CreateDistanceController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_DISTANCE
.distance:CreatePerimeterController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_PERIMETER
.distance:CreateAreaController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_AREA
.distance:CreateCircleAreaController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER.STATE_HANDLER_CREATE_CIRCLE_AREA
.comment-list:ExportCommentController
: Exports the comments of the current document in a specified format, with the format specified by the format attribute:format="XFDF"
, which supports XFDF, FDF, and JSON formats.text-sel:CopySelectedTextController
: Copies the selected text.text-sel:CreateTextHighlightOnSelectedTextController
: Creates a text highlight annotation within the selected text range.text-sel:CreateStrikeoutOnSelectedTextController
: Creates a Strikeout annotation within the selected text range.text-sel:CreateUnderlineOnSelectedTextController
: Creates a Underline annotation within the selected text range.text-sel:CreateBookmarkOnSelectedTextController
: Adds the selected text to the bookmark list.states:RibbonSelectTextImageController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_SELECT_TEXT_IMAGE
.states:RibbonSelectTextAnnotationController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_SELECT_ANNOTATION
.change-color:ChangeColorController
: Used to change the document background color.comment-list:ImportCommentButtonController
: Used to import comment data into the document.states:SelectTextImageController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_SELECT_TEXT_IMAGE
.states:SelectAnnotationController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_SELECT_ANNOTATION
.zoom:ContextMenuZoomActionController
: Controls document view zooming, and needs to specify theaction
attribute. Available values are:fitWidth
,fitHeight
,fitVisible
, and numeric values.ui-rotation:RotateRightController
: Controls document view rotation to the right by 90 degrees.ui-rotation:RotateLeftController
: Controls document view rotation to the left by 90 degrees.annot-opr:ShowAnnotReplyController
: Used to open the commentlist on the left panel, locate the selected annotation, and focus on the reply input box.annot-opr:DeleteAnnotController
: Deletes the selected annotation.annot-opr:ShowAnnotPropertiesController
: Displays the annotation properties dialog.annot-opr:SetPropsDefault
: Sets the current annotation properties as default, which will be used for creating annotations next time.
# Controllers in UIExtension Addons
To retrieve the controller classes in Addons, use the same method as retrieving the built-in controller classes in UIExtensions, but make sure that the Addons have been loaded before retrieval.
- page-template addon:
page-template:ShowPageTemplateDialogController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER
.
- form-designer addon:
form-designer:CreatePushButtonController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_PUSH_BUTTON
.form-designer:CreateCheckBoxController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_CHECK_BOX
.form-designer:CreateRadioButtonController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_RADIO_BUTTON
.form-designer:CreateComboBoxController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_COMBO_BOX
.form-designer:CreateListBoxController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_LIST_BOX
.form-designer:CreateTextController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_TEXT
.form-designer:CreateSignController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_SIGNATURE
.form-designer:CreateImageController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_IMAGE
.form-designer:CreateDateController
: Switches the current StateHandler toSTATE_HANDLER_NAMES.STATE_HANDLER_CREATE_FIELD_DATE
.
- page-editor addon:
page-editor:EditObjectController
: Switches the current StateHandler to "Page Object Editing" tool, including text, image, shape, and gradient objects.page-editor:AddImageAdvController
: Switches the current StateHandler to "Add Image from File" tool.page-editor:AddShapesController
: Switches the current StateHandler to "Create Shape" tool.page-editor:AddTextController
: Switches the current StateHandler to "Add Text" tool.
- fullscreen addon:
full-screen:FullscreenController
: Toggles the full screen mode.
- print addon:
print:ShowPrintDialogController
: Displays the print dialog.
- file-property addon:
fpmodule:FileInfoCallbackController
: Displays the document property dialog.
- h-continuous addon:
h-continuous:HContinuousViewModeController
: Switches the page mode to horizontal continuous page mode.
- export-form addon:
export-form-module:ExportToXMLController
: Exports the form of the current document to an XML format file.export-form-module:ExportToFDFController
: Exports the form of the current document to an FDF format file.export-form-module:ExportToXFDFController
: Exports the form of the current document to an XFDF format file.export-form-module:ExportToCSVController
: Exports the form of the current document to a CSV format file.export-form-module:ExportToTXTController
: Exports the form of the current document to a TXT format file.
- comparison addon:
comparison:ShowCompareFileDialogButtonController
: Displays the document comparison dialog.
- redaction addon:
redaction:RedactionTextAndImageController
: Switches the current StateHandler to the Redaction tool for creating marked text and images.redaction:RedactionController
: Switches the current StateHandler to the Redaction tool for creating marked areas.redaction:RedactionPageController
: Switches the current StateHandler to the Redaction tool for creating marked pages.
With these controllers, we can rewrite the components while reusing the built-in implementation logic of the SDK. Let's take an example of states:HandController
, which can switch the current StateHandler tool to the Hand tool and can determine whether the current tool is the hand tool to activate/deactivate the component:
Of course, some controllers are not as simple as states:HandController
. Here are some of the more special controllers. When using them, we need to follow the methods provided in the examples: