NataliaKondakova
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Widget Toolkit ## Application View Definition Any application that can be loaded into the FIS3 UI is defined via an application definition in JSON format. The definition declares different aspects of an application, its name, its quick access parameters, validations, conditions and the view. The view combines different widgets to form the user interface of the application. The declaration of an instance of a widget looks like the following: ```json { "component": "TextField", "props": { "id": "LocationTextField", "label": "Location", "valueBindingKey": "request.location", "messageBindingKeys": ["request.location"] }, "valueBindingKeyProps": { "valueBindingKey": "value" }, "conditionalProps": {}, "componentProps": [], "children": [] }, ``` This schema is similar to how a component is created in React. When an application is loaded React components are instantiated from those definitions. Usually only the children of a widget will be instantiated as React components, but some widgets do have properties that are actually React components, in this case they need some special treatment: ```json { "component": "Box", "props": { "id": "Box15", "width": 45, "contentOrientation": "horizontal", "buttonAreaContent": [ { "component": "Button", "props": { "id": "ApplyButton", "label": "Filter", "emitOnClick": true, "hero": true }, "conditionalProps": {}, "componentProps": [], "children": [] } ] }, "conditionalProps": {}, "componentProps": ["buttonAreaContent"], "children": [] } ``` In addition there are two properties in the schema that are not strictly necessary, but help to improve performance by avoiding string manipulations: `conditionalProps` and `valueBindingKeyProps`. The `valueBindingKeyProps` property describes how a `valueBindingKey` should be mapped to a specific property. Actually the key is not mapped, but the value retrieved with the key. If the widget has for instance a `startDateValueBindingKey` property, the `valueBindingKeyProps` property would contain the entry `{ "startDateValueBindingKey": "startDateValue" }`. The `conditionalProps` property describes how a conditional property should be mapped to a non conditional property. The name of a conditional property always ends with an `If` and points to a condition. This condition is evaluated at runtime and the result is then passed to the component in the non conditional property. If the widget has for instance a `editableIf` property pointing to the condition `userIsAllowedToEdit`, the `conditionalProps` property would contain the entry `{ "editable": "userIsAllowedToEdit" }`. ## Widget Toolkit Language It would be quite cumbersome to have to write such view definition by hand, without any helpfull hints or validations. Therefore the Application View Definition Language and the Widget Toolkit Language were invented. They are [domain-specific languages](https://en.wikipedia.org/wiki/Domain-specific_language) tailored for easy definition of application views and widgets. The Application View Definition Language is used by an application developer to create the view of an application and its associated generator will generate such application view definitions as described above. The Widget Toolkit Language provides the base information for the Application View Definition Language: The available widgets and how they can be combined to form the user interface of an application. Besides structural elements like the type of a property, it also has validation elements, for instance if a property is mandatory or if a number property may contain negative numbers or how many children a widget might have. The Widget Toolkit Language is design from the point of view of an application developer and not a React or frontend developer, because the application developer has to work with it when defining the view of an application. ### Widget Toolkit Definition A file with the `.wtk` ending defines a widget toolkit. A toolkit mainly defines widgets and how they can be assembled to form a user interface. FIS3 widget toolkit is located in the [ideetools](https://gitlab.hlag.altemista.cloud/fis3/idetools) project in the [fis3.wtk](https://gitlab.hlag.altemista.cloud/fis3/idetools/-/blob/master/widgettoolkits/widgettoolkit-fis/src/main/java/com/hlag/fis/ide/widgettoolkit/fis/fis3.wtk) file. Whenever we implement a new widget or add some changes to an existing one, we must update this file accordingly. Also, our [widget toolkit reference](https://fis3doc.hlag.altemista.cloud/ui/widget-toolkit-reference/overview/widgettoolkit/) is generated based on it. ### Widgets At least one widget in the toolkit needs to be marked as a root widget which is a widget that acts as a container for other widgets at the top level: ```java rootWidget Application ``` Widgets can have children, but often a widget has special constraints as what widgets are allowed as children. Sometimes it may be only one or two very specific widgets, sometimes it may be a specific kind of widgets. For such cases the concept of groups exist: ```java group ActionControl { description: "This group contains widgets that trigger certain actions." } ``` A widget always has a name, a description and at least one property. It can belong to one or more groups and groups can act as valid child types: ```java widget Button { description: "The Button widget lets the user take actions." groups: ActionControl boolean hero { description: "If `true`, indicates the most important button within a tile." defaultValue: false } ... } ``` Sometimes several widgets share a common set of properties, for instance the field widgets. It would be an error prone and tedious to have to repeat such properties in each widget definition. Therefore a widget can inherit properties from one or more widgets. It is possible to not inherit all properties, either because a property does not make sense in the context of the widget or an existing property should be overridden by another property with the same name. A widget can be marked as an `abstract`: ```java abstract widget Field {...} ``` Such a widget is only used in the Widget Toolkit Language to have a place where a set of shared properties can be defined. Such widgets are not usable in the Application View Definition and do not have any corresponding React component, but are used by other widgets in the toolkit to avoid code duplication: ```java widget TextField extends Field {...} ``` ### Properties A property always has a description, it can have a default value (this is for documentation purpose only) and it can be mandatory. It is also possible to make the usage of a property dependent on the presensce or absence of other properties. There are different kind of properties: - const - number (integer or decimal) - boolean - string - combined - child - propchild - reference - Java feature reference A property either represents a single value, multiple values or either a single value or multiple values. If a property is marked as `multiValue` it will always be generated as an array in the resulting view definition. If it is marked as `singleOrMultiValue`, it will only be generated as an array if it contains more than one value. Widget properties can also use `prohibitedIfValueSetOfProperty` field to exclude each other. For example, we always want the widget to receive either non-conditional `editable` property or conditional `editableIf` property. The use of `prohibitedIfValueSetOfProperty` will make them mutually exclusive: ```java boolean editable { ..., prohibitedIfValueSetOfProperty: [editableIf] } javaFeatureReference editableIf { ..., prohibitedIfValueSetOfProperty: [editable] } ``` #### Const The `const` property is used to define some constant value that is used internally in the corresponding React component: ```java const name { description: "The name of the action." value: "fontSize" } ``` #### Number The `integer` or `decimal` property represents a number. The property has different kind of validation settings: - if a negative value is allowed - if a percent value is allowed - if zero as a value is allowed - a lower and upper bound ```java! integer height { description: "The height of the map. One unit of length is equal to the height of one field." } ``` #### Boolean The `boolean` property can either be `true` or `false`: ```java! boolean alwaysUpperCase { description: "If `true`, the value of the field is converted to uppercase." defaultValue: true } ``` #### String The `string` property represents a string. The property can be marked as a`nativeLanguageSupport`, which means the application developer needs to provide values for it in different languages (currently only English): ```java! string label nativeLanguageSupport { description: "The visible text." } ``` This is mainly used for labels and tooltips and does not apply to the frontend, because the frontend will always receive the translated value. A `string` property can have permitted values: ```java! string contentOrientation { description: "Determines how to align the content." defaultValue: "horizontal" permittedValues: { permittedValue: { value: "horizontal" description: "Aligns the content horizontally." }, permittedValue: { value: "vertical" description: "Aligns the content vertically." } } } ``` Sometimes permitted values are also used in the Java coding part of an application, such as for the color property of the `Icon` widget. In such a case Java enums are defined and it is possible to instruct a `string` property to load the permitted values from such an enum: ```java string color { description: "Sets the colour of the icon. This only works for material icons." permittedValuesFromEnum: Color } ``` It is also possible to allow non-permitted values: ```java string name mandatory { description: "The name of the icon to display. This can either be a constant of a FIS3 system icon or the name of a material icon (see https://fonts.google.com/icons?selected=Material+Icons)." permittedValuesFromEnum: Icon allowNonPermittedValues: true } ``` #### Combined A `combined` property is like an object in Javascript, it combines several properties: ```java! combined onFocusLost { description: "Defines what should happen when the field looses focus." prohibitedIfValueSetOfProperty: onFocusLostHandler javaFeatureReference handler { description: "References the method of the controller that gets called." javaFeatureType: method anchor: controller } javaFeatureReference validateValues multiValue { description: "The properties of the model that must be valid before the method of the controller is called." javaFeatureType: field anchor: model } } ``` #### Child and Propchild The `child` and `propchild` properties can contain one or more widgets of a specific type: ```java! child icon[Icon] { description: "The icon used to describe the option." } ``` ```java! propchild rowMenu [DropdownMenu] { description: "Dropdown menu that contains actions for each row" } ``` The difference between those two is, that a `child` property will result in React components in the frontend, whereas a `propchild` property will result in an object in the frontend that has the properties of the respective widget. #### Reference The `reference` property holds the reference to another widget. For instance, an application can have a default save button, therefore the `Application` widget has a `reference` property `defaultSaveButton`: ```java reference defaultSaveButton [ActionControl] { description: "References the button that should be clicked when the user presses the keyboard shortcut for save." scope: Application } ``` #### Java Feature Reference The `javaFeatureReference` property is special, because it references a Java feature, such as a class or a method of a class. This is very far removed from the frontend way of thinking, but necessary for making the Java part of an application work. Usually this kind of property is only used in three places: - to link an application view to its model, controller and conditions class: ```java! javaFeatureReference valueBinding { description: "Binds to a property of the model that provides and receives the value of this field." javaFeatureType: field anchors: [model BoxList.valueBinding DataGrid.valueBinding] assignableToJavaType: String } ``` - for event handlers: ```java! javaFeatureReference onClickHandler { description: "References the method of the controller that gets called when the user clicks on the button." javaFeatureType: method anchor: controller prohibitedIfValueSetOfProperty: onClick } ``` - for conditional properties: ```java! javaFeatureReference hiddenIf { description: "Hides this element if the condition is evaluated to `true`." javaFeatureType: method anchor: fis3.conditions } ``` The model, controller and conditions class references are used for making the live of an application developer easier, because the Application View Language can provide code completion and validation for other properties with this information. The event handler and conditional properties could have been defined as `string` properties, but instead they reference a method in the controller class or the conditions class. The Application View Language can validate those values and also suggest valid values. ## Mapping Properties Except for a few cases React component properties can be easily mapped to widget properties. Any special mappings will be described below. The generator of the Application View Definition Language will take care of converting those widget properties to the expected component properties. ### Identifier Each widget when used in the application view will have a dedicated identifier. This identifier is mapped to the `id` property. Therefore a widget does not need to explicitly declare an `id` property. ### Values A React component uses a `valueBindingKey` property to define a key under which to store and retrieve values from the model (Redux store). The naming of such properties is important. If a component needs for instance a `startDateValue`, it will need a `startDateValueBindingKey` property or to put it another way. Whenever a component needs a value from the model, the corresponding `valueBindingKey` property will map to a `string` property named with the same prefix and `Value` at the end, so `valueBindingKey` maps to `value`, `tooltipValueBindingKey` maps to `tooltipValue`. In the widget toolkit such properties do not end with a `Key` and they are not `string` properties, but `javaFeatureReference` properties and they have to specify valid Java types that must map to primitive values. Those properties are named for instance `valueBinding` or `tooltipValueBinding`. If a component has a property that can either be set dynamically from the model or statically, the corresponding widget should define two properties, such as a `tooltip` `string` property and a `tooltipValueBinding` `javaFeatureReference` property. The widget should not have a property `tooltipValue`. This needs to be reflected in the component also as two properties, such as `tooltip` and `tooltipValue`. More information about value binding can also be found [here](https://gitlab.hlag.altemista.cloud/fis3/commons-ui/commons-ui-frontend/-/blob/master/docs/development/value-binding.md). ### Conditional Properties Conditional properties are a concept that most of the time is shielded from a React component. The name of a conditional property always ends with `If` and will be passed without the `If` to the component, for instance `editableIf` will be passed as `editable`. This concept is fully described in separate [Conditionals](https://hackmd.io/YLgVUpVXRwWTm8dY-4HJUg?both#-conditionalsmd-file) document. A conditional property which is a `string` property in a component, needs to be a `javaFeatureReference` property in a widget, referencing a Java method of a conditions class: ```java! javaFeatureReference editableIf { description: "References a condition. If the condition evalutes to `false`, the field is read-only, the user cannot edit its content." javaFeatureType: method anchor: conditions prohibitedIfValueSetOfProperty: [editable] } ``` Sometimes a component does have a property that can be set to a fixed value or can be set conditionally during runtime, a good example would be the `editable` property. A component might only declare an `editable` `boolean` property because it does not care whether that property has been set at compile time or conditionally during runtime. The corresponding widget definition on the other hand, must care. So it requires one of two properties: an `editable` `boolean` property or an `editableIf` `javaFeatureReference` property. If a property should only be a conditional property, the component would again only have for instance a `hidden` `boolean` property and now the widget would also have only one property, a `hiddenIf` `javaFeatureReference` property. Another special case is setting the value of a property conditionally where the value is not a boolean, e.g. the name of an icon. In this case the widget needs to declare a `combined` property, with two properties, an `if` `javaFeatureReference` property and a `value` property. The component still declares one property with the desired type, such as `string` for the name of an icon. ### Event Properties A component can have `boolean` properties which tell the component to send specific events, such as `emitOnClick`. Those properties are mapped to the so called handler properties in the corresponding widget, because those properties specify the controller method that should handle the event. The naming convention is easy, for instance an `emitOnClick` `boolean` property maps to a `onClickHandler` `javaFeatureReference` property. Sometimes more needs to happen then just sending an event, such as asking the user if modified values should be saved or validate values before sending an event. Again following the naming convention a component will have additional properties, such as a `confirmSaveOnClick` `boolean` property or a `validateValuesOnClick` `array` `string` property. In this case the widget needs a combined property called for instance `onClick`, which needs to have a `handler` `javaFeatureReference` property and optionally for instance a `confirmSave` `boolean` property or a `validateValues` `multivalue` `string` property: ```java combined onClick { description: "Defines what should happen when the user clicks on the button." prohibitedIfValueSetOfProperty: onClickHandler javaFeatureReference handler { description: "References the method of the controller that gets called." javaFeatureType: method anchor: controller } javaFeatureReference validateValues multiValue { description: "The properties of the model that must be valid before the method of the controller is called." javaFeatureType: field anchor: model } boolean confirmSave { description: "If `true`, will ask the user if changes should be saved or discarded." defaultValue: false } } ``` ### Value Validations There exists one special property `valueValidations`, which is used in field widgets. It defines conditions that when evaluated determine if a field contains a valid value or not. ```java combined valueValidations multiValue { description: "Defines how the value should be validated." javaFeatureReference failIf { description: "References a condition that fails the validation if it evaluates to `true`." javaFeatureType: method anchor: conditions prohibitedIfValueSetOfProperty: failIfNot } javaFeatureReference failIfNot { description: "References a condition that fails the validation if it evaluates to `false`." javaFeatureType: method anchor: conditions prohibitedIfValueSetOfProperty: failIf } boolean contentValidation { description: "If set to `true,` will show the error message when the field looses focus." defaultValue: false } } ``` In the widget toolkit this property is a `multivalue` `combined` property. The generator of the Application View Definition Language will split this property into a property attached to the widget that follows the naming convention for value bindings and an entry in the global `validations` map at the root level of the application definition file. So if a component has a `valueBindingKey` and the application developer should be able to write validations for that value, the widget needs a `valueValidations` `multivalue` `combined` property. For a `startDateValueBindingKey` that property would need to be named `startDateValueValidations`. The combined property either contains a `failIf` or a `failIfNot` `javaFeatureReference` property, that references the condition that should be evaluated. Additionally, an `error` `string` property for the error message needs to be defined, and a `contentValidation` `boolean` property. The `contentValidation` `boolean` property determines when the validation should happen, when the user types a value (`true`) or when an event is fired (`false` default).

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully