Theme
MonacoEditor
The Monaco editor widget was built with extensibility in mind. The PrimeFaces widget is a JSF wrapper component that lets you integrate the editor easily in a JSF page and provides several options for the most common features. Sometimes, however, it may become necessary to customize the editor event further. In that case, you can make use of the extensive client-side JavaScript API provided by the Monaco editor.

To do so, specify the extender option on the editor. This lets you set a custom JavaScript object with several callback methods for the lifecycle of the Monaco editor. For example, you can modify the editor options before the editor is created, or add TypeScript declaration files for improved IntelliSense. The example below loads the declaration files for JQuery from the DefinitelyTyped GitHub repo and adds them to the editor. This enables autocomplete and docs for JQuery function.

For the inline widget, you can just specify a JavaScript expression that evaluates to an extender object. For the framed widget, you will need to specify an URL to a JavaScript file that creates the extender and writes it to window.MonacoEnvironment.Extender. See the panel to the right for more info about the extender object. Please note that for the framed widget, the extender is run in the iframe context and will not have access to JQuery nor to PrimeFaces related functions.

The extenders you see in the example below use the fetch API and other modern JavaScript features. If you need to support old browsers, consider using XMLHttpRequest instead of fetch instead.

Finally, you can also check out the Monaco editor playground which contain many more exapmles of how you can use the client-side API to customize the editor.
Additional type declarations (JQuery)This example illustrates how you can add custom type declaration files to the editor. It loads the type declarations files for JQuery -- try hovering over the JQuery functions in the editor to the right or try typing some code to see the autocomplete feature in action.

To do so, you should add the beforeCreate to your extender object. Use the third parameter wasLibLoaded to check whether the Monaco editor library was reloaded -- if not, there's no need to add declarations files again.

Then you can add the required type declaration files via monaco.languages.typescript.javascriptDefaults.addExtraLib (if you are editing a JavaScript file) or monaco.languages.typescript.typescriptDefaults.addExtraLib (if you are editing a TypeScript file). See the Monaco editor API DOC for more info on that function.

Finally, you may wonder from where you should load the declaration files. You could add the declaration inline into the extender script, which may be a viable option for small declaration files. For larger files, it is recommended you load the declaration file from a network resource. Note that the beforeCreate hook of the extender may return a Promise. If it does, the Monaco editor widget will wait until that Promise resolves and only create the editor once it does.

See also https://github.com/DefinitelyTyped/DefinitelyTyped, the repository for high quality TypeScript type definitions for many popular JavaScript libraries.
Run
Source

                <p:staticMessage id="extenderInfo" severity="info" styleClass="monacoEditorMessage" escape="false"
  summary="#{monacoEditorController.extenderName}" detail="#{monacoEditorController.extenderInfo}" />

<h:panelGrid columns="3">
  <!-- Apply the selected extender -->
  <p:commandLink id="applyExtender" partialSubmit="true" styleClass="ui-button ui-button-text-icon-right"
    actionListener="#{monacoEditorController.onMonacoExtenderRun}"
    process="@this,monacoExtender,monacoEditorWrapper" update="customExtenderInline,monacoEditorWrapper">
    <span class="ui-button-icon-right ui-icon ui-c pi pi-play" style="color:white"></span>
    <span class="ui-button-text ui-c" style="color:white">Run</span>
  </p:commandLink>

  <!-- Select extender example -->
  <p:outputLabel for="extenderExample" value="Extender example: " />
  <p:selectOneMenu id="extenderExample" value="#{monacoEditorController.extenderExample}">
      <f:selectItems value="#{monacoEditorController.extenderExamples}" />
      <p:ajax 
        process="extenderInfo,monacoExtender,monacoEditorWrapper"
        listener="#{monacoEditorController.onExtenderExampleChange}"
        update="customExtenderInline,extenderInfo,monacoExtender,monacoEditorWrapper" />
  </p:selectOneMenu>
</h:panelGrid>

<div style="display:flex">
  <!-- Monaco editor for editing the extender -->
  <h:panelGroup id="monacoExtenderWrapper" layout="block" style="flex:1" styleClass="monacoExtenderBox">
      <pe:monacoEditorFramed id="monacoExtender" widgetVar="monacoExtender"
          value="#{monacoEditorController.valueExtender}" scheme="file"
          extender="#{resource['js/monacoExtender.js']}"
          iframeUrlParams="{extender: 'monaco', language: 'javascript', tsCheck: true}"
          editorOptions="#{monacoEditorController.editorOptionsExtender}"
          width="100%" height="500px" autoResize="true"/>
  </h:panelGroup>

  <!-- Actual editor with the extender applied -->
  <h:panelGroup id="monacoEditorWrapper" layout="block" style="flex:1" styleClass="monacoEditorBox">
      <pe:monacoEditor id="monacoEditor" widgetVar="monacoEditor"
          rendered="#{empty monacoEditorController.extenderError}"
          value="#{monacoEditorController.value}"
          extender="window.MonacoEnvironment.Extender||{}"
          editorOptions="#{monacoEditorController.editorOptions}"
          width="100%" height="500px" autoResize="true" />
      <h:panelGroup layout="block" 
        rendered="#{not empty monacoEditorController.extenderError}" styleClass="monacoEditorError">
        <strong>Could not load custom Monaco editor extender, error was:</strong>
        <pre>#{monacoEditorController.extenderError}</pre>
      </h:panelGroup>
  </h:panelGroup>
</div>
            
Components and more
Documentation pe:monacoEditor
Attributes (move mouse over the names to see data types)
Name Description
id Unique identifier of the component in a naming container.
rendered Boolean value to specify the rendering of the component, when set to false component will not be rendered.
style CSS style(s) to be applied when this component is rendered.
styleClass Space-separated list of CSS style class(es) to be applied when this element is rendered. This value is passed through as the "class" attribute to the generated markup.
binding An EL expression referring to a server side UIComponent instance in a backing bean.
widgetVar Name of the client side widget.
value Value of the component.
readonly Defines if the editor is readonly.
disabled Defines if the editor is disabled.
tabindex The tab index to assign to the editor. If not given, no tab index will be assigned.
converter An EL expression or a literal text that defines a converter for the component. When it's an EL expression, it's resolved to a converter instance. In case it's a static text, it must refer to a converter id.
required Marks component as required.
requiredMessage Message to display when required field validation fails.
converterMessage Message to display when conversion fails.
validatorMessage Message to display when validation fails.
validator A method expression referring to a method validating the input.
onfocus Client side callback when the editor area receives focus.
onblur Client side callback when the editor area loses focus.
onchange Client side callback when the editor content changes.
oninitialized Client side callback when the editor was rendered.
onpaste Client side callback when text was pasted into the editor.
onmousedown Client side callback when a mousedown event was triggered on the editor area.
onmousemove Client side callback when a mousemove event was triggered on the editor area.
onmouseup Client side callback when a mouseup event was triggered on the editor area.
onkeyup Client side callback when a keyup event was triggered on the editor area.
onkeydown Client side callback when a keydown event was triggered on the editor area.
onkeypress Client side callback when a keypress (onDidType) event was triggered on the editor area.
customThemes Allows you to register custom themes with the editor via Java. This must be a Map<String, org.primefaces.extensions.model.monacoeditor.EditorStandaloneTheme>. It maps between the name of the theme and the styling data for that theme. You can then specify the theme name for the theme option in the editorOptions.
locale Locale for the user interface. Can be either a java.util.Locale object or a string with the locale code. Built-in languages are "bg", "de", "en", "es", "fr", "hu", "it", "ja", "ko", "ps", "pt_BR", "ru", "tr", "uk", "zh_CN", and "zh_TW". To use a custom language or translation, you can specify a language file with custom translations via the option localeUrl.
localeUrl For custom language files. If given, this is used instead of the built-in language files. This URL must point to a JavaScript file that, when executed, adds the localization to window.MonacoEnvironment.Locale["LOCALE_CODE"], where LOCALE_CODE is the value you set for locale. See the language file the widget downloads (when locale is not set to English) for an example and all available messages that need to be translated.
extender

An extender object to further customize the monaco editor via JavaScript. This can be either:

  • unset, in which case no further customization is performed
  • or a JavaScript expression that evaluates to an extender object
The extender object may have one or more of the following optional properties:
  • beforeCreate(editorWidget, options). Called before the monaco editor is created. It is passed the current options object that would be used to initialize the monaco editor. If this callback does not return a value, the options are used as they were passed to the callback. The callback is allowed to modify the passed options object. If the callback returns an options object, that options object is used instead. If it returns a thenable/Promise, the monaco editor is created only once the Promise resolves (successfully). If the Promise resolves with an options object, that options object is used to create the editor. See IEditorConstructionOptions for all editor options.
  • afterCreate(editorWidget). Called after the editor was created.
  • beforeDestroy(editorWidget). Called before the editor is destroyed, eg. when updating a component via AJAX.
  • afterDestroy(editorWidget). Called after the editor is destroyed, eg. when updating a component via AJAX. Note that editorWidget.getMonaco() now returns undefined.
  • createModel(editorWidget, options). Called when a model needs to retrieved or created. The options contains value (current value that should be set on the model by the extender), url (default URL that was determined for the model), language (requested code language), and editorOptions (monaco editor constructor options). Should return the model. When it returns nothing, the default mechanism for creating a model is used. Note that editorWidget.getMonaco() returns undefined as the monaco editor was not created yet.
  • createEditorOverrideServices(editorWidget, options). Called when the monaco editor is created. May return an object with services that should be overriden. See here on github for details on the available services. The options are the editor constructor options that will be used to create the editor, they are readonly and must not be changed.
  • createWorker(editorWidget, moduleId, label). Called when a worker for additional language support needs to be created. By default, monaco editor ships with the workers for JSON, CSS, HTML, and TYPESCRIPT. The label is the name of the language, eg. css or javascript. Must return the worker to be used for the given language. Note that editorWidget.getMonaco() returns undefined as the monaco editor was not created yet.
scheme The monaco editor requires a unique URI for an opened model (i.e. the code currently being edited). This is the scheme (protocol) for that URI. Defaults to inmemory.
directory The monaco editor requires a unique URI for an opened model (i.e. the code currently being edited). This is the directory (path) for that URI, with parts separated by slashes. If not given, it is taken from the client ID of this component.
basename The monaco editor requires a unique URI for an opened model (i.e. the code currently being edited). This is the basename for that URI, without the extension. If not given, default to 'file'.
extension The monaco editor requires a unique URI for an opened model (i.e. the code currently being edited). This is the extension for that URI, with or without the period. If not given, it is inferred from the (code) language.
width Width of the editor with CSS units, set as an inline style. For example 500px or 100%/code>. Set this to the empty string in case you want to size the editor via CSS.
height Height of the editor with CSS units, set as an inline style. For example 500px or 100%/code>. Set this to the empty string in case you want to size the editor via CSS.
editorOptions Options for the Monaco code editor. This is a simple wrapper around the JavaScript API, see IEditorConstructionOptions The code language can be set via the EditorOptions#setLanguage option.
autoResize If true, resizes the editor automatically when the iframe element changes its size. Please note that this makes uses of the new ResizeObserver API and works only in newer browers. This widget checks whether ResizeObserver API is available, and when it is not, no resizing is performed. To support resizing for older browsers, search for a ResizeObserver polyfill. If you know when the size of the editor conainer could have changed, you can resize the editor manually via PF("editorWidgetVar").layout()
PrimeFaces Extensions Showcase - © 2011-2021,PrimeFaces: 10.0.0,PrimeFaces Extensions: 10.0.5,JSF: Apache MyFaces JSF-2.3 Core API 2.3.9,Server: jetty/9.4.36.v20210114,Build time: 2021-08-28 16:46
occured!