diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/_index.md deleted file mode 100644 index a3c119b2656..00000000000 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Mendix 8" -url: /apidocs-mxsdk/apidocs/pluggable-parent-8/ -weight: 60 -description: Information on Pluggable Widget API in Mx8. ---- - -The following Mendix 8 pluggable widget API documents are available here: - -* [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/property-types-pluggable-widgets-8/) for Mendix 8 -* [Client APIs Available to Pluggable Widgets](/apidocs-mxsdk/apidocs/client-apis-for-pluggable-widgets-8/) for Mendix 8 -* [Preview Appearance APIs for Pluggable Widgets](/apidocs-mxsdk/apidocs/studio-apis-for-pluggable-widgets-8/) for Mendix 8 -* [Compare Pluggable and Custom Widgets](/apidocs-mxsdk/apidocs/differences-between-pluggable-and-custom-widgets/) for Mendix 8 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/_index.md deleted file mode 100644 index cf15bc3ed2f..00000000000 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/_index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Mendix 9" -url: /apidocs-mxsdk/apidocs/pluggable-parent-9/ -weight: 50 -description: Information on the Pluggable Widget API in Mx9. ---- - -The following Mendix 9 pluggable widget API documents are available here: - -* [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types-9/) for Mendix 9 -* [Client APIs Available to Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-9/) for Mendix 9 -* [Preview Appearance APIs for Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis-9/) for Mendix 9 -* [Configuration Module API for Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-config-api-9/) for Mendix 9 -* [Declaring Native Dependencies](/apidocs-mxsdk/apidocs/pluggable-widgets-native-dependencies-9/) for Mendix 9 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/_index.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/_index.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/_index.md index 2b7850ebfae..36758fc1c18 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/_index.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/_index.md @@ -1,6 +1,6 @@ --- title: "Pluggable Widgets API" -url: /apidocs-mxsdk/apidocs/pluggable-widgets/ +url: /apidocs-mxsdk/apidocs/pluggable-widgets-10/ description: "This API helps you to understand pluggable widgets, how they extend app functionality, and how they can be built to interact with Mendix's APIs in Mx10." no_list: false description_list: true @@ -285,7 +285,7 @@ Note that the **Common** and **Appearance** tabs are added to your widget config ## Widget Property -This section will explain the shape of the widget property. For more detailed information on widget properties, see [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/). Every `property` tag in the Widget Properties Definition has a shape similar to this: +This section will explain the shape of the widget property. For more detailed information on widget properties, see [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types-10/). Every `property` tag in the Widget Properties Definition has a shape similar to this: ```xml diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/_index.md new file mode 100644 index 00000000000..3e6d3ea83b8 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/_index.md @@ -0,0 +1,329 @@ +--- +title: "Client APIs" +linktitle: "Client APIs for Pluggable Widgets" +url: /apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-10/ +description: A guide for understanding the client APIs available to pluggable widgets in Mx10. +weight: 20 +--- + +## Introduction + +The main API the Mendix Platform provides to a pluggable widget client component is the props the component receives. These props resemble the structure of properties specified in the widget definition XML file (a structure described in [Pluggable Widgets API](/apidocs-mxsdk/apidocs/pluggable-widgets/)). A property's attribute type affects how the property will be represented to the client component. Simply, an attribute's type defines what will it be. You can find the more details on property types and the interfaces that property value can adhere to in [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/). To see examples of pluggable widgets in action, see [How To Build Pluggable Widgets](/howto/extensibility/pluggable-widgets/) + +The Mendix Platform also exposes a few JavaScript modules, specifically extra Mendix APIs as well as existing libraries, like React, that client components must share with the platform to function properly. For more information on exposed libraries, see the [Exposed Libraries](#exposed-libraries) section below. + +## Bundling + +Mendix does not provide you code as an *npm package*, which is the approach commonly used by JavaScript libraries. Instead, Mendix provides you modules available during execution. Hence, if you are using a module bundler like [webpack](https://webpack.js.org/), you should configure it to mark these modules as [externals](https://webpack.js.org/configuration/externals/). + +This process can be cumbersome, so it is recommended you use this [tools package](https://www.npmjs.com/package/@mendix/pluggable-widgets-tools) which contains the correctly-configured bundlers to work with pluggable widgets. If you follow best practices and use the [Mendix Pluggable Widget Generator](https://www.npmjs.com/package/@mendix/generator-widget) to scaffold your widget, then this package is added automatically. + +## Standard Properties {#standard-properties} + +Alongside the props that correspond to the properties specified in widget definition XML file, the props listed below are always passed to a client component. + +### Name + +In Mendix Studio Pro, every widget must have a name configured. The primary usage of a widget name is to make its component identifiable in the client so that it can be targeted using [Selenium](/howto/integration/selenium-support/) or Appium test automation. In web apps, the Mendix Platform automatically adds the class `mx-name-{widgetName}` to a widget so that no extra action from a component developer is required. Unfortunately, this solution is not possible for [native mobile apps](/refguide/mobile/). For native mobile apps a component developer must manually pass a given `string` `name` prop to an underlying React Native [testID](https://facebook.github.io/react-native/docs/view#testid). + +### Class + +A user can specify multiple classes for every widget. They can do this either directly by configuring a [class](/refguide/common-widget-properties/#class) property in Studio Pro, or by using design properties. In web apps, the Mendix Platform creates a CSS class string from the configuration and passes it as a `string` `class` prop to every client component. Unfortunately, React Native does not have similar support for classes. Therefore in native mobile apps a component will not receive `class` prop, but a `style` prop instead. + +### Style + +A user can specify a custom CSS for every widget on a web page by using the [style](/refguide/common-widget-properties/#style) property. This styling is passed to a client component through an optional `style` prop of the type `CSSProperties`. + +On native pages, the meaning of a `style` prop is very different. First of all, a user cannot specify the aforementioned inline styles for widgets on a native page. So a `style` prop is used to pass styles computed based on configured classes. A client component will receive an array with a single [style object](/refguide/mobile/designing-mobile-user-interfaces/widget-styling-guide/#style-objects) with all applicable styles combined. + +### TabIndex + +If a widget uses a TabIndex prop [system property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#tabindex), then it will receive a configured `Tab index` through a `number` `tabIndex` property, except in the case when a configured tab index is on its default value of 0. Currently, `tabIndex` is not passed to widgets used on native pages. + +## Property Values + +### ActionValue {#actionvalue} + +`ActionValue` is used to represent actions, like the [On click](/refguide/on-click-event/#on-click) property of an action button. For any action except **Do nothing**, your component will receive a value adhering to the following interface. For **Do nothing** it will receive `undefined`. The `ActionValue` prop appears like this: + +```ts +export interface ActionValue { + readonly canExecute: boolean; + readonly isExecuting: boolean; + execute(): void; +} +``` + +#### canExecute {#canexecute} + +The flag `canExecute` indicates if an action can be run under current conditions. This prevents executing actions that are not allowed by the app's security settings. User roles can be set in the microflows and nanoflows, allowing users to call them. For more information on user roles and security, see the [Module Security Reference Guide](/refguide/module-security/). + +You can also employ this flag when using a **Call microflow** action triggering a microflow with a parameter. Such an action cannot be run until a parameter object is available, for example when a parent data view has finished loading. Attempting to `execute` an action that cannot be run will have no effect, and generates a debug-level warning message. + +The exception to this behavior is when the `ActionValue` is returned by [`ListActionValue.get()`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listactionvalue). In this case, the flag will be true when not all arguments have been loaded. Calling `execute()` for an action with loading arguments will run the action as soon as all arguments become available. While waiting, `isExecuting` will be set to `true` and subsequent calls to `execute()` are ignored. If any arguments become unavailable after loading, the action will not run and a debug-level warning message will be logged. + +#### isExecuting {#isexecuting} + +The flag `isExecuting` indicates whether an action is currently running. A long-running action can take seconds to complete. Your component might use this information to render an inline loading indicator which lets users track loading progress. Often it is not desirable to allow a user to trigger multiple actions in parallel. Therefore, a component (maybe based on a configuration) can decide to skip triggering an action while a previous execution is still in progress. + +Note that `isExecuting` indicates only whether the current action is running. It does not indicate whether a target nanoflow, microflow, or object operation is running due to another action. + +#### execute {#execute} + +The method `execute` triggers the action. It returns nothing and does not guarantee that the action will be started synchronously. But when the action does start, the component will receive a new prop with the `isExecuting` flag set. + +When the action property [defines action variables](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#action-xml-elements), the `execute()` method expects an object map containing a property for each variable. The variables may be passed as undefined, but need to be set explicitly. + +Given an action property that defines two `Decimal` variables `lat` and `long`, and a `String` variable named `label`, its `execute()` method accepts the following input: + +```ts +interface MapWidgetProps { + onClick: ActionValue<{ lat: Option, long: Option, label: Option }> +} + +onClick.execute({ + lat: new Big(51.907), + long: new Big(4.488), + label: undefined +}); +``` + +### DynamicValue {#dynamic-value} + +`DynamicValue` is used to represent values that can change over time and is used by many property types. It is defined as follows: + +```ts +export type DynamicValue = + | { readonly status: ValueStatus.Available; readonly value: X } + | { readonly status: ValueStatus.Unavailable; readonly value: undefined } + | { readonly status: ValueStatus.Loading; readonly value: X | undefined }; + +export const enum ValueStatus { + Loading = "loading", + Unavailable = "unavailable", + Available = "available" +} +``` + +A component will receive a `DynamicValue` where type `X` depends on a property configuration. For example, for the [TextTemplate property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#texttemplate) it will be `DynamicValue`, but for the [expression property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#expression) `X` will depend on a configured `returnType`. + +Though the type definition above looks complex, it is fairly simply to use because a component can always read `DynamicValue.value`. This field either contains an actual value, such as an interpolated `string` in the case of a Text template, or the last known correct value if the value is being recomputed, such as when a parent Data view reloads its Data source. In other cases the value is set as `undefined`. + +`DynamicValue.status` provides a component with additional information about the state of a dynamic value, as well as if the component should handle them differently. This is done using a [discriminated union](https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions) that covers the following situations: + +* When `status` is `ValueStatus.Available`, then the dynamic value has sufficient information to be computed, and the result is exposed in `value`. +* When `status` is `ValueStatus.Unavailable`, then the dynamic value does not have such information such as when a parent Data view’s Data source has returned nothing. The `value` is then always `undefined`. +* When `status` is `ValueStatus.Loading`, then the dynamic value is awaiting for the required information to arrive. This happens when a parent Data view is either waiting for its object to load or is reloading it due to a [refresh in client](/refguide/change-object/#refresh-in-client). + * In case a dynamic value was previously in a `ValueStatus.Available` state, then the previous `value` is still returned. This is done so that a component can keep showing the previous value if it doesn’t need to handle `Loading` explicitly. This prevents flickering: a state when a displayed value rapidly changes between loading and not loading several times. + * In other cases, the `value` is `undefined`. This is a common situation while a page is still being loaded. + +### EditableValue {#editable-value} + +`EditableValue` is used to represent values, either an attribute or a variable, that can be changed by a pluggable widget client component and is passed only to [attribute properties](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#attribute). It is defined as follows: + +```ts +export interface EditableValue { + readonly status: ValueStatus; + readonly readOnly: boolean; + + readonly value: T | undefined; + setValue(value: T | undefined): void; + readonly validation: string | undefined; + setValidator(validator?: (value: T | undefined) => string | undefined): void; + + readonly displayValue: string; + setTextValue(value: string): void; + + readonly formatter: ValueFormatter; + setFormatter(formatter: ValueFormatter | undefined): void; + + readonly universe?: T[]; +} +``` + +A component will receive `EditableValue` where `X` depends on the configured `attributeType`. + +`status` is similar to one exposed for `DynamicValue`. It indicates if the value's loading has finished and if loading was successful. Similarly to `DynamicValue`, `EditableValue` keeps returning the previous `value` when `status` changes from `Available` to `Loading` to help a widget avoid flickering. + +The flag `readOnly` indicates whether a value can actually be edited. It will be true, for example, when a widget is placed inside a Data view that is not [editable](/refguide/data-view/#editable), or when a selected attribute is not editable due to [access rules](/refguide/access-rules/). The `readOnly` flag is always true when a `status` is not `ValueStatus.Available`. Any attempt to edit a value set to read-only will have no affect and incur a debug-level warning message. + +The value can be read from the `value` field and modified using `setValue` function. Note that `setValue` returns nothing and does not guarantee that the value is changed synchronously. But when a change is propagated, a component receives a new prop reflecting the change. + +When setting a value, a new value might not satisfy certain validation rules — for example when an attribute is selected and the new value is bigger than the underlying attribute allows. In this case, your change will affect only `value` and `displayValue` received through a prop. Your change will not be propagated to an object’s attribute and will not be visible outside of your component. The component will also receive a validation error text through the `validation` field of `EditableValue`. + +It is possible for a component to extend the defined set of validation rules. A new validator — a function that checks a passed value and returns a validation message string if any — can be provided through the `setValidator` function. A component can have only a single custom validator. The Mendix Platform ensures that custom validators are run whenever necessary, for example when a page is being saved by an end-user. It is best practice to call `setValidator` early in a component's lifecycle — specifically in the [componentDidMount](https://en.reactjs.org/docs/react-component.html#componentdidmount) function. + +In practice, many client components present values as nicely formatted strings which take locale-specific settings into account. To facilitate such cases `EditableValue` exposes a field `displayValue` which is the formatted version of `value`, and a method `setTextValue` — a version of `setValue` that takes care of parsing. `setTextValue` also validates that a passed value can be parsed and assigned to the target's value type. Similarly to `setValue`, a change to an invalid value will not be propagated further than the prop itself, but a `validation` is reported. Note that if a value cannot be parsed, the prop will contain only a `displayValue` string and `value` will become undefined. + +There is a way to use more the convenient `displayValue` and `setTextValue` while retaining control over the format. A component can use a `setFormatter` method passing a formatter object: an object with `format` and `parse` methods. The Mendix Platform provides a convenient way of creating such objects for simple cases. An existing formatter exposed using a `EditableValue.formatter` field can be modified using its `withConfig` method. For complex cases formatters still can be created manually. A formatter can be reset back to default settings by calling `setFormatter(undefined)`. + +The optional field `universe` is used to indicate the set of all possible values that can be passed to a `setValue` if a set is limited. Currently, `universe` is provided only when the edited value is of the Boolean or enumeration [types](/refguide/attributes/#type). + +### ModifiableValue {#modifiable-value} + +`ModifiableValue` is used to represent values that can be changed by a pluggable widget client component. It is passed only to [association properties](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#association), and is defined as follows: + +```ts +export interface ModifiableValue { + readonly status: ValueStatus; + readonly readOnly: boolean; + + readonly value: Option; + readonly setValue: (value: Option) => void; + readonly validation: Option; + readonly setValidator: (validator?: (value: Option) => Option) => void; +} +``` + +The type received by the component for the association property depends on the allowed association types: + +* If only references are allowed, the component receives a `ReferenceValue` defined as `ModifiableValue & { type: "Reference" };` +* If only reference sets are allowed, the client gets a `ReferenceSetValue` defined as `ModifiableValue & { type: "ReferenceSet" };` + +Finally, when both association types are allowed the type is a union of `ReferenceValue` and `ReferenceSetValue` and the widget should check the `type` to determine if a reference or reference set is configured and act accordingly in the code. Checking the type will also [narrow](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#handbook-content) to the correct type in TypeScript. + +```ts +if (association.value === undefined) { + return "None"; +} + +if (association.type === "Reference") { + return textTemplate.get(association.value); +} else { + return association.value.map((objectItem) => textTemplate.get(objectItem)).join(","); +} +``` + +`status` is similar to the one exposed for `DynamicValue`. It indicates if the value's loading has finished and if loading was successful. Similarly to `DynamicValue`, `ModifiableValue` keeps returning the previous `value` when `status` changes from `Available` to `Loading` to help a widget avoid flickering. + +The flag `readOnly` indicates whether a value can actually be edited. It will be true, for example, when a widget is placed inside a data view that is not [editable](/refguide/data-view/#editable), or when a selected attribute is not editable due to [access rules](/refguide/access-rules/). The `readOnly` flag is always true when a `status` is not `ValueStatus.Available`. Any attempt to edit a value set to read-only will have no affect and incur a debug-level warning message. + +The value can be read from the `value` field and modified using the `setValue` function. The `value` contains an `ObjectItem` or an `ObjectItem[]` based on the configured association. The `ObjectItem` can be passed to the `get` function of any [linked property value](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#linked-values) which is linked to the selectable object's datasource. + +When setting a value, the `ObjectItem` must be items from the selectable object's data source. Note that `setValue` returns nothing and does not guarantee that the value is changed synchronously. But when a change is propagated, a component receives a new prop reflecting the change. + +It is possible for a component to extend the defined set of validation rules. A new validator — a function that checks a passed value and returns a validation message string if any — can be provided through the `setValidator` function. A component can have only a single custom validator. The Mendix Platform ensures that custom validators are run whenever necessary, for example when a page is being saved by an end-user. It is best practice to call `setValidator` early in a component's lifecycle — specifically in the [componentDidMount](https://en.reactjs.org/docs/react-component.html#componentdidmount) function. + +### IconValue {#icon-value} + +`DynamicValue` is used to represent icons: small pictograms in the Mendix Platform. Those can be static or dynamic file- or font-based images. An icon can only be configured through an [icon](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#icon) property. `IconValue` is defined as follows: + +```ts +interface GlyphIcon { + readonly type: "glyph"; + readonly iconClass: string; +} + +interface WebImageIcon { + readonly type: "image"; + readonly iconUrl: string; +} + +interface Icon { + readonly type: "icon"; + readonly iconClass: string; +} + +interface NativeImageIcon { + readonly type: "image"; + readonly iconUrl: Readonly; +} + +export type WebIcon = GlyphIcon | WebImageIcon | Icon | undefined; +export type NativeIcon = GlyphIcon | NativeImageIcon | undefined; +export type IconValue = WebIcon | NativeIcon; +``` + +In practice, `WebIcon` and `NativeIcon` are usually passed to a `Icon` component provided by Mendix, since this provides a convenient way of handling all types of icons at once. For more information on `Icon`, see the [Icon](#icon) section below. + +### ImageValue{#imagevalue} + +`DynamicValue` is used to represent static or dynamic images. An image can be configured only through an [image](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#image) property. `ImageValue` is defined as follows: + +```ts +export interface WebImage { + readonly uri: string; + readonly name: string; + readonly altText?: string; +} +export type NativeImage = Readonly; +export type ImageValue = WebImage | NativeImage; +``` + +`NativeImage` can be passed to a `mendix/components/native/Image` component provided by Mendix for native widgets. `WebImage` can be passed to react-dom’s `img` component. + +### FileValue {#filevalue} + +`DynamicValue` is used to represent files. A file can be configured only through a [file](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#file) property. `FileValue` is defined as follows: + +```ts +export interface FileValue { + readonly uri: string; + readonly name: string; +} +``` + +### List values{#list-values} + +`ListValue` is used to represent a list of objects for the [datasource](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#datasource) property. See [List Values](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/) for more information about usage of `ListValue` and associated property values. + +### SelectionValue {#selection-value} + +`SelectionValue` is used to represent selections. It is passed only to [selection properties](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#selection), and is defined as follows: + +```ts +declare interface SelectionValue { + readonly selection: T; + readonly setSelection: (value: T) => void; +} +``` + +The type received by the component for the selection property depends on the allowed selection types: + +* If only single selection is allowed, the component receives a `SelectionSingleValue` defined as `SelectionValue> & { type: "Single" };`. +* If only multi selection is allowed, the client gets a `SelectionMultiValue` defined as `SelectionValue & { type: "Multi" };`. + +Finally, when both selection types are allowed, then the type is a union of `SelectionSingleValue` and `SelectionMultiValue` and the widget should check the `type` to determine if a single or multi selection is configured and act accordingly in the code. Checking the type will also [narrow](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#handbook-content) to the correct type in TypeScript: + +```ts +if (selection?.selection === undefined) { + return "None"; +} + +if (selection.type === "Single") { + selection.setSelection(objectItem); +} else { + selection.setSelection([objectItem]); +} +``` + +## Exposed Modules + +### Icon {#icon} + +Mendix Platform exposes two versions of an `Icon` react component: `mendix/components/web/Icon` and `mendix/components/native/Icon`. Both components are useful helpers to render `WebIcon` and `NativeIcon` values respectively. They should be passed through an `icon` prop. The native `Icon` component additionally accepts `color` (`string`) and `size` (`number`) props. + +## Exposed Libraries {#exposed-libraries} + +### React and React Native {#exposed-react} + +The Mendix Platform re-exports [react](https://www.npmjs.com/package/react), [react-dom](https://www.npmjs.com/package/react-dom), and [react-native](https://www.npmjs.com/package/react-native) packages to pluggable widgets. `react` is available to all components. `react-dom` is available only to components running in web or hybrid mobile apps. `react-native` is available only to components running in native mobile apps. + +Mendix provides you with `react` version `17.*.*` (in npm terms `^17.0.1`) and a matching version of `react-dom`. For `react-native` Mendix exposes version `0.63.*` (in npm terms `~0.63.3`). + +Patch versions might change from one minor release of Mendix to another. + +### Big.js + +The Mendix Platform uses [big.js](https://www.npmjs.com/package/big-js) to represent and operate on numbers. Mendix 9.0 re-exports version 6.0. + +## Native Dependencies + +Sometimes for widgets it is necessary to rely on the existing community libraries of `react` and `react-native`. With widgets targeting a web platform it is easy to include those libraries as they can be shipped together with a widget by bundling them into the widget's package. That is often not the case with libraries targeting a native platform, as some of them require a setup of Android- and iOS-specific code into a Mendix native app or [Make It Native](/refguide/getting-the-make-it-native-app/) app. For more information, see [Declaring Native Dependencies](/apidocs-mxsdk/apidocs/pluggable-widgets-native-dependencies/). + +## Read More + +* [Pluggable Widgets API Documentation](/apidocs-mxsdk/apidocs/pluggable-widgets/) +* [Pluggable Widget Property Types Documentation](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/) +* [How to Build Pluggable Widgets](/howto/extensibility/pluggable-widgets/) +* [Declaring Native Dependencies](/apidocs-mxsdk/apidocs/pluggable-widgets-native-dependencies/) diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md new file mode 100644 index 00000000000..5ced8c50851 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md @@ -0,0 +1,851 @@ +--- +title: "List Values" +url: /apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values-10/ +description: A guide to understanding the list of objects for the datasource property in Mx10. +--- + +## Introduction + +`ListValue` is used to represent a list of objects for the [datasource](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#datasource) property. Corresponding list item values represent properties of different types linked to a [datasource](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#datasource) property. + +## ListValue {#listvalue} + +When a [`datasource`](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#datasource) property with `isList="true"` is configured for a widget, the client component gets a list of objects represented as a `ListValue`. This type allows detailed access and control over the data source. + +```ts +export interface ObjectItem { + id: GUID; +} + +export interface ListValue { + status: ValueStatus; + + offset: number; + limit: number; + setOffset(offset: number): void; + setLimit(limit: Option): void; + requestTotalCount(needTotalCount: boolean): void; + hasMoreItems?: boolean; + totalCount?: number; + items?: ObjectItem[]; + + sortOrder: SortInstruction[]; + filter: Option; + setSortOrder(sortOrder: Option): void; + setFilter(filter: Option): void; +} +``` + +### Pagination {#listvalue-pagination} + +The `offset` and `limit` properties specify the range of objects retrieved from the datasource. The `offset` is the starting index and the `limit` is the number of requested items. By default, the `offset` is *0* and the `limit` is `undefined` which means all the datasource's items are requested. You can control these properties with the `setOffset` and `setLimit` methods. This allows a widget to not show all data at once. Instead it can show only a single page when you set the proper offset and limit, or the widget will load additional data whenever it is needed if you increase the limit. + +The following code sample sets the offset and limit to load datasource items for a specific range: + +```ts +this.props.myDataSource.setOffset(20); +this.props.myDataSource.setLimit(10); +``` + +You can use the `setOffset` and `setLimit` methods to create a widget with pagination support (assuming widget properties are configured as follows): + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + pageSize: number; +} +``` + +To set the number of items requested by the datasource you can use the `setLimit` in the constructor of the widget: + +```ts +export default class PagedWidget extends Component { + constructor(props: PagedWidgetProps) { + super(props); + + props.myDataSource.setLimit(props.pageSize); + } +} +``` + +To switch to a different page you can change the offset with the `setOffset` method: + +```tsx +const ds = this.props.myDataSource; +const current = this.props.myDataSource.offset; + + +``` + +The `hasMoreItems` property indicates whether there are more objects beyond the limit of the most recent list. When a widget does not show all the records immediately by setting a limit with `setLimit` and allows the user to load additional data, you can use this property to make it clear in the user interface that the user has reached the end of the list. + +The following code sample shows a 'load more' button only when there is more data available, and loads additional data when the user clicks the button: + +```tsx +const currentLimit = this.props.myDataSource.limit; +this.props.myDataSource.hasMoreItems && + +``` + +When a `limit` is set to *0*, that case is handled in a special way. In this case `ListValue` will avoid sending a request to the server to retrieve data and will immediately return an empty result. This property can be used to build widgets that load their data "lazily": only when and if a specific condition is met. + +The following code sample loads the data only if a button is pressed: + +```tsx +export default const LazyWidget = (props: LazyWidgetProps) => { + useMemo(() => props.myDataSource.setLimit(0), []); + return props.myDataSource.items?.length ? ( + props.myDataSource.items.map((i) =>
Item
) + ) : ( + + ); +} +``` + +The `totalCount` property is the total number of objects the datasource can return. Calculating a total count might consume significant resources and is only returned when the widget indicated needs a total count by calling the `requestTotalCount(true)` method. When possible, please use the `hasMoreItems` instead of the `totalCount` property. + +The following code sample shows how to request the total count to be returned: + +```ts +export default class PagedWidget extends Component { + constructor(props: PagedWidgetProps) { + super(props); + + props.myDataSource.requestTotalCount(true); + } +} +``` + +The `setOffset` and `setLimit` are supported on all [data sources](/refguide/data-sources/#list-widgets). For the `XPath` and `Database` data sources, only the requested page is returned to the client. For other data sources the full set is returned to the client, but the widget will only receive the requested page in the `items` property. + +### Sorting {#listvalue-sorting} + +It is possible to set a specific sort order for items in the list using `setSortOrder` method and get the current sort order via `sortOrder` field. When a new sort order is set, widget will receive new results on next re-render. + +`setSortOrder` method accepts one argument which should be an array of `SortInstruction`s. Also `undefined` could be passed to `setSortOrder` to restore default sort order. + +`SortInstruction` is defined as an array of two elements: + +```ts +type SortInstruction = [id: ListAttributeId, dir: SortDirection]; +``` + +The first element of `SortInstruction` type is `id` of an attribute property linked to the datasource. This lets the widget specify which attribute should be used for sorting. Though not every attribute could be used for sorting, for some attributes sorting may be disallowed. To determine if an attribute could be used for sorting `sortable` flag of its attribute property has to be checked. This flag specifies if it is possible to use particular attribute for sorting. See [Attribute ID, Sortable and Filterable Flags](#listattributevalue-id-sortable-filterable) section for more information about attribute `id` and `sortable` flag. + +The second attribute of `SortInstruction` type is a literal string representing the sort direction, either `"asc"` or `"desc"`. + +The following code examples show how to apply sorting to the property `myDataSource` based on linked attributes `attributeAge` and `attributeName`: + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + attributeAge: ListAttributeValue; // Integer + attributeName: ListAttributeValue; // String +} +``` + +Set ascending sort order based on attribute represented by `attributeAge` property with the following code: + +```ts +if (this.props.attributeAge.sortable) { + // sort by age ascending + const sortInstrs = [ + [this.props.attributeAge.id, "asc"] + ]; + this.props.myDataSource.setSortOrder(sortInstrs); +} else { + console.warn("Can't apply sorting. Attribute Age is not sortable"); +} +``` + +The following code sample shows how to sort on multiple attributes at the same time: + +```ts +if (this.props.attributeAge.sortable && this.props.attributeName.sortable) { + // sort by age descending, and then by name ascending (within age groups) + const sortInstrs = [ + [this.props.attributeAge.id, "desc"], + [this.props.attributeName.id, "asc"], + ]; + this.props.myDataSource.setSortOrder(sortInstrs); +} else { + console.warn("Can't apply sorting. Attribute Age and/or Name is not sortable"); +} +``` + +Reset to default sort order by passing `undefined` as the following code shows: + +```ts +this.props.myDataSource.setSortOrder(undefined); +``` + +The `setSort` method is supported for all [data sources](/refguide/data-sources/#list-widgets). For `Database` and `XPath` data sources the sorting is done by the back end. For all the other data sources the sorting is done by the client. + +### Filtering {#listvalue-filtering} + +It is possible to set filtering conditions for items of a datasource. `setFilter()` method accepts filter conditions and applies filtering. `filter` field represents the current filter condition. + +`setFilter` accepts only a specially created object of type `FilterCondition` that describes desired filtering behavior. It is possible to create a filter conditions object using functions provided in `mendix` module under `mendix/filters/builders` path. Those functions we call filter builders. Also `undefined` could be passed to `setFilter` to clear filtering conditions. + +Some examples of builder functions are `equals`, `greaterThan`, `lessThanOrEqual` for filtering on `DateTime` or `Decimal` attributes. Functions like `startsWith`, `contains` are useful for filtering on `String` attributes. Filtering based on associations is also possible. For example, you can use `equals` with references and `contains` with reference sets. + +The following code samples show how to use filter builders and apply filtering to a data source property with three linked attributes and two linked associations: + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + mySelectableObjects: ListValue; + myAttributeString: ListAttributeValue; + myAttributeBoolean: ListAttributeValue; + myAttributeNumber: ListAttributeValue; + myAssociationReference: ListReferenceValue; + myAssociationReferenceSet: ListReferenceSetValue; +} +``` + +The `setFilter` method is supported for all [data sources](/refguide/data-sources/#list-widgets). For `Database` and `XPath` data sources the filtering is done by the back end. For all the other data sources the filtering is done by the client. In both cases the widget will receive the filtered items in the `items` property. + +#### Simple Filtering {#simple-filtering} + +To apply a simple filter based on the value of an attribute represented by `myAttributeString` property the following code may be used: + +```ts +import { attribute, literal, startsWith } from "mendix/filters/builders"; + +// in the widget code +if (this.props.myAttributeString.filterable) { + const filterCond = startsWith(attribute(this.props.myAttributeString.id), literal("B")); + this.props.myDataSource.setFilter(filterCond); +} else { + console.log("Attribute is not filterable"); +} +``` + +The first step the code takes is checking for the possibility to use filtering on `myAttributeString` property by checking the `filterable` flag. Then the `filterCond` filter condition is constructed, which specifies that attribute represented by `myAttributeString` should start with character `"B"`. The `setFilter` call applies the filter, and on the next re-render the component gets only items where the value of an attribute represented by property `myAttributeString` is starting with `"B"`. + +Similarly, code like this can apply a condition where the value on an attribute represented by `myAttributeBoolean` property is set to true: + +```ts +import { attribute, literal, equals } from "mendix/filters/builders"; + +// in the widget code +if (this.props.myAttributeBoolean.filterable) { + const filterCond = equals(attribute(this.props.myAttributeBoolean.id), literal(true)); + this.props.myDataSource.setFilter(filterCond); +} else { + console.log("Attribute is not filterable"); +} +``` + +Code like this can apply a condition to match only objects that are associated with another object: + +```ts +import { association, literal, notEquals, empty } from "mendix/filters/builders"; + +// in the widget code +if (this.props.myAssociationReference.filterable) { + const filterCond = notEquals(association(this.props.myAssociationReference.id), empty()); + this.props.myDataSource.setFilter(filterCond); +} else { + console.log("Association is not filterable"); +} +``` + +Similarly, code like this can apply a condition to match only the objects that are associated with at least the first two objects from the selectable objects data source: + +```ts +import { association, literal, notEquals, contains } from "mendix/filters/builders"; + +// in the widget code +if (this.props.myAssociationReferenceSet.filterable) { + // assuming those two objects are available + const objectItem1 = this.props.mySelectableObjects.items[0]; + const objectItem2 = this.props.mySelectableObjects.items[1]; + + const filterCond = contains(association(this.props.myAssociationReferenceSet.id), literal([objectItem1, objectItem2])); + this.props.myDataSource.setFilter(filterCond); +} else { + console.log("Association is not filterable"); +} +``` + +The following code sample shows how to remove the current filtering condition: + +```ts +this.props.myDataSource.setFilter(undefined); +``` + +#### Advanced Filtering {#advanced-filtering} + +In some use cases it is necessary to apply more complex filtering conditions. For example if a use case requires fetching only items where `myAttributeString` starts with `"B"` and `myAttributeBoolean` is set to `true`, or items where `myAttributeNumber` is greater than `10` and `myAssociationReference` is associated with another object while `myAssociationReferenceSet` is not associated with any other objects. In order to construct such a condition, special filter builders `and` and `or` have to be used. The following code sample shows how to use them. Note that checks for the `filterable` flag have been omitted for simplicity. Real widgets should always take the `filterable` flag into account. + +```ts +import { attribute, association, literal, startsWith, equals, notEquals, greaterThan, and, or } from "mendix/filters/builders"; + +// in the widget code +if (/* check that all properties are filterable */) { + const filterCond = or( + and( + startsWith(attribute(this.props.myAttributeString.id), literal("B")), + equals(attribute(this.props.myAttributeBoolean.id), literal(true)) + ), + and( + greaterThan(attribute(this.props.myAttributeNumber.id), literal(10)), + notEquals(association(this.props.myAssociationReference.id), empty()), + equals(association(this.props.myAssociationReferenceSet.id), empty()) + ) + ); + this.props.myDataSource.setFilter(filterCond); +} else { + console.log("Some attribute is not filterable"); +} +``` + +### Reloading {#listvalue-reload} + +It is possible to reload items of a datasource. The `reload()` method triggers a new fetch from the underlying data source, preserving existing `filter`, `offset`, `limit`, `requestTotalCount`, and `sortOrder` properties. The `reload()` method accepts no arguments. + +### Working With Actual Data + +The `items` property contains all the requested data items of the datasource. However, it is not possible to access domain data directly from `ListValue`, as every object is represented only by GUID in the `items` array. Instead, a list of items may be used in combination with other properties, for example with a property of type [`attribute`](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#attribute), [`action`](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#action), or [`widgets`](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#widgets). See the next section for detailed information about working with different property types in combination with `ListValue`. + +### View State {#view-state} + +View state is a mechanism of storing the current state of a page when user navigates away from the page and restoring that state when user navigates back to the page. For example user has some sorting order applied in a DataGrid widget on an overview page and navigates away to a detail page. When user gets back to the overview page, the DataGrid widget will be initialized with previously used sorting order. + +View state works transparently for a widget, no additional steps needed from the widget in order to benefit from view state mechanism. + +The following information of a `ListView` is getting automatically stored and restored: + +* Pagination state (`limit` and `offset` fields) +* Sorting state (`sortOrder` field) +* Filtering state (`filter` field) + +### Status of the List Value Items {#status-of-the-list-value-items} + +The `status` property provides the component with additional information about the state of the items and how the component should handle them: + +```tsx +export const enum ValueStatus { + Loading = "loading", + Unavailable = "unavailable", + Available = "available" +} + +if (this.props.listValue.status === ValueStatus.Available) { + return ( +
+ ... +
+ ); +} else if (this.props.listValue.status === ValueStatus.Loading) { + return

Loading... Please, wait...

; +} else if (this.props.listValue.status === ValueStatus.Unavailable) { + return

There are no available items to show.

; +} +``` + +More specifically, the `status` property functions as follows: + +* When `status` is `ValueStatus.Available`, then the list value items are accessible, and the result is exposed in the `items` array. +* When `status` is `ValueStatus.Unavailable`, then the list does not have any available data and the `items` array is `undefined`. This can be the case if the data source depends on a surrounding data view which has no data. +* When `status` is `ValueStatus.Loading`, then the list is waiting for new data to arrive. This can be triggered by a change in data that the data source depends on (such as a parent data view) or by an entity update, which occurs if an object of that type is committed or deleted. If this is done from a microflow, a [refresh in client](/refguide/change-object/#refresh-in-client) is also required. + * If the list value was previously in a `ValueStatus.Available` state, then the previous `items` array is still returned. This allows a component to keep showing the previous items if it does not need to handle the `Loading` state explicitly, which prevents flickering. + * In other cases, the `items` is `undefined`. This happens if a page is still being loaded or if the previous state was `ValueStatus.Unavailable`. + +## Linked Property Values {#linked-values} + +### ListActionValue {#listactionvalue} + +`ListActionValue` represents action that may be applied to items from `ListValue`. The `ListActionValue` is an object and its definition is as follows: + +```ts +export interface ListActionValue { + get: (item: ObjectItem) => ActionValue; +} +``` + +In order to call an action on a particular item of a `ListValue` first an instance of `ActionValue` should be obtained by calling `ListActionValue.get` with the item (assuming widget properties are configured as follows): + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + myListAction: ListActionValue; +} +``` + +The following code sample shows how to call `myListAction` on the first element from the `myDataSource`. + +```ts +const actionOnFirstItem = this.props.myListAction.get(this.props.myDataSource.item[0]); + +actionOnFirstItem.execute(); +``` + +In this code sample, checks of status `myDataSource` and availability of items are omitted for simplicity. See the [ActionValue section](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#actionvalue) for more information about the usage of `ActionValue`. + +### ListAttributeValue {#listattributevalue} + +`ListAttributeValue` represents an [attribute property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#attribute) that is linked to a data source. +This allows the client component to access attribute values on individual items from a `ListValue`. `ListAttributeValue` is an object and its definition is as follows: + +```ts +export interface ListAttributeValue { + get: (item: ObjectItem) => EditableValue; // NOTE: EditableValue obtained from ListAttributeValue always readonly + + id: ListAttributeId; + sortable: boolean; + filterable: boolean; + + type: AttributeType; + + formatter: ValueFormatter; + universe: Option; // only for attributes of type Enumeration +} +``` + +#### Obtaining Attribute Value {#obtaining-attribute-value} + +{{% alert color="warning" %}} +Due to a technical limitation it is not yet possible to edit attributes obtained via `ListAttributeValue`. `EditableValue`s returned by `ListAttributeValue` are always **readonly**. +{{% /alert %}} + +In order to work with the attribute value of a particular item of a `ListValue` first an instance of `EditableValue` should be obtained by calling `ListAttributeValue.get` with the item. The type `` depends on the allowed value types as configured for the attribute property. + +Let's take a look at some example. Assuming widget properties are configured as follows with `myAttributeOnDatasource` property allowing attribute of type `string`: + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + myAttributeOnDatasource: ListAttributeValue; +} +``` + +The following code sample shows how to get an `EditableValue` that represents a read-only value of an attribute of the first element from the `myDataSource`. + +```ts +const attributeValue = this.props.myAttributeOnDatasource.get(this.props.myDataSource.items[0]); +``` + +Note: in this code sample checks of status of `myDataSource` and availability of items are omitted for simplicity. See [EditableValue section](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#editable-value) for more information about usage of `EditableValue`. + +#### Attribute ID, Sortable and Filterable Flags {#listattributevalue-id-sortable-filterable} + +`id` field of type `ListAttributeId` represents the unique randomly generated string identifier of an attribute. That identifier could be used when applying sorting and filtering on a linked data source property to identify which attribute should be used for sorting and/or filtering. For more information, see the [Sorting](#listvalue-sorting) and [Filtering](#listvalue-filtering) sections. + +Fields `sortable` and `filterable` specify if the attribute could be used for sorting and/or filtering. Those flags have to be checked before a widget applies filtering or sorting on a data source property. Any attempt to filter on a non-filterable attribute or sort on a non-sortable attribute leads to an error during the execution time. + +#### Attribute Type + +The [attribute](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#attribute) property defines which attribute types can be configured for that property. For example, an attribute property may be configured to allow attributes of type `String` and `Integer` in order to present progress. While this is convenient for users, it may require additional work for developers by processing different data types. + +It is possible to determine the type of attribute by checking the `type` field on an attribute property. The following code sample shows how to check the attribute type on the property named `myAttributeOnDatasource`: + +```ts +if (this.props.myAttributeOnDatasource.type === "String") { + console.log("String attribute"); +} else if (this.props.myAttributeOnDatasource.type === "Integer") { + console.log("Integer attribute"); +} else { + console.log("Not a String/Integer attribute"); +} +``` + +#### Formatter and Universe + +The `formatter` field represents the default formatter used on values obtained by the `get` function. + +The optional `universe` field represents an array of possible values for an attribute. For more information, see the `universe` field of [EditableValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#editable-value). + +### ListReferenceValue and ListReferenceSetValue {#listassociationvalue} + +`ListReferenceValue` and `ListReferenceSetValue` are both used to represent an [association property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#association) that is linked to a data source. This allows the client component to access associated values of individual items from a `ListValue`. `ListReferenceValue` and `ListReferenceSetValue` are both objects and their definitions are as follows: + +```ts +export type ListReferenceValue = ListAssociationValue & { type: "Reference" }; + +export type ListReferenceSetValue = ListAssociationValue & { type: "ReferenceSet" }; + +export interface ListAssociationValue { + get: (item: ObjectItem) => DynamicValue; + + id: ListAssociationId; + filterable: boolean; +} +``` + +#### Obtaining Association Values + +In order to work with an object or objects that are associated with a particular item returned by `ListValue`, first an instance of `DynamicValue` (for `ListReferenceValue`) or `DynamicValue` (for `ListReferenceSetValue`) should be obtained by calling `get` with the item. + +If the association property has been configured to allow both types of associations, the type of the property is defined as `ListReferenceValue | ListReferenceSetValue` and a check on its `type` should be done to narrow down the type. For more information, see the [Association Type](#association-type) section. + +Consult the following example code, which assumes widget properties are configured with the `myAssociationOnDatasource` property allowing association of type `Reference`: + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + mySelectableObjects: ListValue; + myAssociationOnDatasource: ListReferenceValue; + myAttributeOnSelectableObjects: ListAttributeValue; +} +``` + +The following code example shows how to get a `DynamicValue` that represents a read-only value of an associated object of the first element from the `myDataSource`: + +```ts +const associationValue = this.props.myAssociationOnDatasource.get(this.props.myDataSource.items[0]); +``` + +This will return an `ObjectItem` representing the associated object, because in this example the widget is configured to allow only singular associations. If you want to access the individual attribute values of this associated object, you may use an attribute property linked to the selectable objects data source and pass the associated object to it. For more information, see [Obtaining Attribute Value section](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#obtaining-attribute-value). + +Please note these code samples omit checks of `myDataSource` status and availability of items for simplicity. See [DynamicValue section](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#dynamic-value) for more information on the usages of `DynamicValue`. + +#### Association ID and Filterable Flags {#listassociationvalue-id-filterable} + +The `id` field of type `ListAssociationId` represents the unique randomly-generated string identifier of an association. That identifier can be used when applying filtering on a linked data source property to identify which association should be used for filtering. For more information, see the [Filtering](#listvalue-filtering) section. + +The `filterable` field specifies if the association can be used for filtering. This flag has to be checked before a widget applies filtering on a data source property. An attempt to filter on a non-filterable association leads to an error during the execution time. + +#### Association Type {#association-type} + +The [association](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#association) property determines which association types could be configured for that property. For example, an association property may be configured to allow associations of type `Reference` and not `ReferenceSet`. + +It is possible to determine the type of association by checking the `type` field on an association property. This is useful if the property has been configured to allow both references and reference sets. The following code sample shows how to check the association type on the property named `myAssociationOnDatasource`: + +```ts +if (this.props.myAssociationOnDatasource.type === "Reference") { + console.log("Reference association"); +} else { + // TypeScript will narrow it down to "ReferenceSet" when the type is not equal to "Reference" + console.log("ReferenceSet association"); +} +``` + +### ListWidgetValue {#listwidgetvalue} + +`ListWidgetValue` represents a [widget property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#widgets) that is linked to a data source. This allows the client component to render child widgets with items from a `ListValue`. +`ListWidgetValue` is an object and its definition is as follows: + +```ts +export interface ListWidgetValue { + get: (item: ObjectItem) => ReactNode; +} +``` + +For clarity, consider the following example using `ListValue` together with the `widgets` property type. When the `widgets` property named `myWidgets` is configured to be tied to a `datasource` named `myDataSource`, the client component props appear as follows: + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + myWidgets: (i: ObjectItem) => ReactNode; +} +``` + +Because of the above configurations, the client component may render every instance of widgets with a specific item from the list like this: + +```ts +this.props.myDataSource.items.map(i => this.props.myWidgets.get(i)); +``` + +When the `widgets` property is not required, there may not be any child widgets configured. In that case the value of the widgets property will be `undefined` (as in the example above `myWidgets`). + +### ListExpressionValue {#listexpressionvalue} + +`ListExpressionValue` represents an [expression property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#expression) or [text template property](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/#texttemplate) that is linked to a data source. This allows the client component to access expression or text template values for individual items from a `ListValue`. `ListExpressionValue` is an object and its definition is as follows: + +```ts +export interface ListExpressionValue { + get: (item: ObjectItem) => DynamicValue; +}; +``` + +The type `` depends on the return type as configured for the expression property. For a text template property, this type is always `string`. + +In order to work with the expression or text template value of a particular item of a `ListValue`, first an instance of `DynamicValue` should be obtained by calling `ListExpressionValue.get` with the item (assuming widget properties are configured as follows with an expression of type `boolean`): + +```ts +interface MyListWidgetsProps { + myDataSource: ListValue; + myExpressionOnDatasource: ListExpressionValue; + myTextTemplateOnDatasource: ListExpressionValue; +} +``` + +The following code sample shows how to get a `DynamicValue` that represents the value of an expression for the first element from the `myDataSource`. + +```ts +const expressionValue = this.props.myDataSource.myExpressionOnDatasource.get(this.props.myDataSource.item[0]); +``` + +## Filter Helpers{#filter-helpers} + +### Value Helpers {#filter-value-helpers} + +Two basic helpers that allow to represent attributes and literal values in filter conditions are `attribute` and `literal` helpers. When creating a filter condition, every attribute or literal value has to be wrapped with a corresponding helper. + +#### Attribute + +The `attribute` helper takes one argument of type `ListAttributeId`. See [ListAttributeValue](#listattributevalue). + +The following code sample shows how to apply `attribute` helper and use its result in constructing a filter condition: + +```ts +const attrA = attribute(this.props.myAttributeA.id); +const filterCondition = equals(attrA, literal("Bob")); +``` + +Attribute types available for filtering: + +* `Boolean` +* `DateTime` +* `AutoNumber` +* `Integer` +* `Long` +* `Decimal` +* `Enum` +* `String` +* `HashString` + +Attribute types **not** available for filtering: + +* `Binary` +* `EnumSet` +* `ObjectReference` +* `ObjectReferenceSet` + +#### Literal + +The `literal` helper takes one argument. Accepted argument types are: + +* Boolean values for `Boolean` attribute types +* String literals for `String`, `HashString` and `Enumeration` attribute types +* `BigJS` numbers for `AutoNumber`, `Integer`, `Long` and `Decimal` attribute types +* `Date` objects for `DateTime` attribute type +* `undefined` for any attribute type + +The following code sample shows how to use `literal` helper: + +```ts +const falsy = literal(false); // for Boolean +const bob = literal("Bob"); // for String, HashString, Enumeration +const meaningOfLife = literal(new BigJS(42)); // for AutoNumber, Integer, Long, Decimal +const now = literal(new Date()); // for DateTime +const undef = literal(undefined); +``` + +### Basic Helpers + +#### Equals + +The `equals` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Accepts attributes and literals of any type. + +The following code sample shows how to use `equals` helper: + +```ts +const attrA = attribute(this.props.myAttributeA.id); +const name = literal("Bob"); + +// filter keeps items where value equals "Bob" +const filterCondition = equals(attrA, name); +``` + +#### NotEqual + +The `notEqual` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Accepts attributes and literals of any type. + +The following code sample shows how to use `notEqual` helper: + +```ts +const attrA = attribute(this.props.myAttributeA.id); +const name = literal("Bob"); + +// filter keeps items where value not equal to "Bob" +const filterCondition = notEqual(attrA, name); +``` + +#### GreaterThan + +The `greaterThan` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `HashString`, `Enumeration`, `AutoNumber`, `Integer`, `Long` `Decimal`, `DateTime` attributes and their corresponding literals. + +The following code sample shows how to use `greaterThan` helper: + +```ts +const attr = attribute(this.props.myAttributeA.id); +const meaningOfLife = literal(new BigJS(42)); + +// filter keeps items where value is greater than 42 +const filterCondition = greaterThan(attr, meaningOfLife); +``` + +#### LessThan + +The `lessThan` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `HashString`, `Enumeration`, `AutoNumber`, `Integer`, `Long` `Decimal`, `DateTime` attributes and their corresponding literals. + +The following code sample shows how to use `lessThan` helper: + +```ts +const attr = attribute(this.props.myAttributeA.id); +const meaningOfLife = literal(new BigJS(42)); + +// filter keeps items where value is less than 42 +const filterCondition = lessThan(attr, meaningOfLife); +``` + +#### GreaterThanOrEqual + +The `greaterThanOrEqual` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `HashString`, `Enumeration`, `AutoNumber`, `Integer`, `Long` `Decimal`, `DateTime` attributes and their corresponding literals. + +The following code sample shows how to use `greaterThanOrEqual` helper: + +```ts +const attr = attribute(this.props.myAttributeA.id); +const meaningOfLife = literal(new BigJS(42)); + +// filter keeps items where value is greater than or equals 42 +const filterCondition = greaterThanOrEqual(attr, meaningOfLife); +``` + +#### LessThanOrEqual + +The `lessThanOrEqual` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `HashString`, `Enumeration`, `AutoNumber`, `Integer`, `Long` `Decimal`, `DateTime` attributes and their corresponding literals. + +The following code sample shows how to use `lessThanOrEqual` helper: + +```ts +const attr = attribute(this.props.myAttributeA.id); +const meaningOfLife = literal(new BigJS(42)); + +// filter keeps items where value is less than or equals 42 +const filterCondition = lessThanOrEqual(attr, meaningOfLife); +``` + +### String Conditions + +#### Contains + +The `contains` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `Integer`, `Long`, `Decimal` attributes and `String` literals. + +The following code sample shows how to use `contains` helper: + +```ts +const attrStr = attribute(this.props.myAttributeA.id); // string attribute +const subStr = literal("secret"); + +// filter keeps items where value has a substring "secret" +// like "my secret password", "secret file", "top secret" +const filterCondition1 = contains(attrStr, subStr); + +// also works with numeric attributes +const attrNum = attribute(this.props.myAttributeB.id); // integer attribute +const subNum = literal("1337"); + +// filter keeps items where value has sequence of numbers "1337" +// like "133700", "1231337", "913379" +const filterCondition2 = contains(attrNum, substrNum); +``` + +#### StartsWith + +The `startsWith` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `Integer`, `Long`, `Decimal` attributes and `String` literals. + +The following code sample shows how to use `startsWith` helper: + +```ts +const attrStr = attribute(this.props.myAttributeA.id); // string attribute +const subStr = literal("secret"); + +// filter keeps items where value starts with substring "secret" +// like "secret file", but not "my secret password" or "top secret" +const filterCondition1 = startsWith(attrStr, subStr); + +// also works with numeric attributes +const attrNum = attribute(this.props.myAttributeB.id); // integer attribute +const subNum = literal("1337"); + +// filter keeps items where value stats with sequence of numbers "1337" +// like "133700", but not "1231337" or "913379" +const filterCondition2 = startsWith(attrNum, substrNum); +``` + +#### EndsWith + +The `endsWith` helper takes two arguments produced by [Value helpers](#filter-value-helpers). +Allows only `String`, `Integer`, `Long`, `Decimal` attributes and `String` literals. + +The following code sample shows how to use `endsWith` helper: + +```ts +const attrStr = attribute(this.props.myAttributeA.id); // string attribute +const subStr = literal("secret"); + +// filter keeps items where value ends with substring "secret" +// like "top secret", but not "my secret password" or "secret file" +const filterCondition1 = startsWith(attrStr, subStr); + +// also works with numeric attributes +const attrNum = attribute(this.props.myAttributeB.id); // integer attribute +const subNum = literal("1337"); + +// filter keeps items where value ends with sequence of numbers "1337" +// like "1231337", but not "133700" or "913379" +const filterCondition2 = startsWith(attrNum, substrNum); +``` + +### Logic Conditions + +#### And + +The `and` helper is used to combine other conditions in *logical and* operation. Takes 2 or more arguments. + +The following usage example specifies that *all conditions have to be true* for an object in order to appear in the resulting filtered set: + +```ts +const filterCondition = and( + startsWith(attribute(this.props.myAttributeA.id), literal("Hi")), // myAttributeA starts with string "Hi" + equals(attribute(this.props.myAttributeB.id), literal(5)), // myAttributeB equals 5 + greaterThan(attribute(this.props.myAttributeC.id), literal(new Date())) // myAttributeC greaterThan current date and time +); +``` + +#### Or + +The `or` helper is used to combine other conditions in *logical or* operation. Takes 2 or more arguments. + +The following usage example specifies that *at least one condition have to be true* for an object in order to appear in the resulting filtered set: + +```ts +const filterCondition = or( + endsWith(attribute(this.props.myAttributeA.id), literal("Z")), // myAttributeA ends with string "Z" + graterThan(attribute(this.props.myAttributeB.id), literal(10)), // myAttributeB greater that 10 + equals(attribute(this.props.myAttributeC.id), literal(true)) // myAttributeC equals True +); +``` + +#### Not + +The `not` helper inverts a condition. It takes one argument. + +The following usage example specifies that `myAttributeA` have to start with any letter except `"X"` by inverting `startsWith` condition: + +```ts +const filterCondition = not( + startsWith(attribute(this.props.myAttributeA.id), literal("X")), +); +``` diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-config-api.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-config-api.md new file mode 100644 index 00000000000..f521990dda8 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-config-api.md @@ -0,0 +1,658 @@ +--- +title: "Configuration Module API" +url: /apidocs-mxsdk/apidocs/pluggable-widgets-config-api-10/ +description: A guide for understanding the configuration module API which influences the behavior of pluggable widgets in Mx10. +weight: 35 +--- + +## Introduction + +A pluggable widget's configuration module allows for several modeler experience improvements. For example, you can hide widget properties based on conditions, add consistency checks to validate the widget's configuration, and customize your widget's appearance in **Structure mode**. + +It is usually located in a JavaScript file using the same name as the widget’s XML file, ending with *.editorConfig.js*. For example, next to *TextBox.xml* would be a *TextBox.editorConfig.js*. + +The file is expected to be in CommonJS format, using the `exports` object to export functions. + +## Widget Developer Console {#widget-dev-console} + +Errors that are related to the configuration module are shown in the Widget Developer Console. This console is separate from the default console and can be found in the [View menu](/refguide/view-menu/). + +## Customizing the Widget’s Properties + +To customize the properties available in Studio Pro for the pluggable widget, the module should export a `getProperties` function. Two parameters are passed to this function: + +* The current configured values, following the [Values API](/apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis/#values) +* The default property configuration + +```typescript +function getProperties( + values: ValuesAPI, + defaultConfiguration: Properties +): Properties +``` + +Using this API, it is possible to dynamically show or hide certain properties based on configured values. + +{{% alert color="info" %}} +Please note that when a property is hidden, its value will be cleared. +{{% /alert %}} + +{{% alert color="info" %}} +Be advised that hiding a property which is required according to the XML will still give a consistency error that it is required. We therefore discourage hiding properties that are required.

If a property is only required on a specific condition, it should not be marked as required in the XML. Instead of this, you should manually implement a check using the custom validation function. +{{% /alert %}} + +The expected property configuration structure is as follows: + +* `Properties` is expected to be an array of `PropertyGroups` +* A `PropertyGroup` is an object that must have a `caption`: + * It is possible to have two levels of `PropertyGroup` objects, which can be achieved by giving the top-level groups a `propertyGroups` field containing an array of `PropertyGroup` objects + * Alternatively, a property group can contain one or more `Property` objects in the `properties` field +* A `Property` is an object that must have a `key` that corresponds to a property `key` from the widget XML, and a `caption` field: + * Optionally, a `description` field can be returned with a description of the property + * If the property is of type `object` it requires a more complex configuration + * The `objects` array field of the `Property` object contains the sub-objects’ properties (each sub-object will require an entry as an `ObjectProperties` object in this array) + * The `properties` array field of the `ObjectProperties` object contains the sub-object's properties in form of an array of `PropertyGroup` objects + * The object grid can be customized by using the property's `objectHeaders` and the object's `captions` array field (for more information, see the [Customizing Object Grids](#customize-object-grids) section) + +```typescript +type Properties = PropertyGroup[]; + +type PropertyGroup = { + caption: string; + propertyGroups?: PropertyGroup[]; + properties?: Property[]; +} + +type Property = { + key: string; + caption: string; + description?: string; + objectHeaders?: string[]; // used for customizing object grids + objects?: ObjectProperties[]; +} + +type ObjectProperties = { + properties: PropertyGroup[]; + captions?: string[]; // used for customizing object grids +} +``` + +Here is an example of how this structure looks as JavaScript object, based on the following widget XML snippet: + +```XML + + + + Graph caption + The caption of this graph + + + + + Data caption + The caption of the data set + + + Data points + + + + + + X value + + + + Y value + + + + + + + + +``` + +Assuming the widget is configured with three data points, the following would be the first object passed (the values): + +```typescript +{ + caption: "My graph", + dataCaption: "Points", + dataPoints: [ + { x: 0, y: 10 }, + { x: 1, y: 12 }, + { x: 2, y: 5 } + ] +} +``` + +The default configuration would then be: + +```typescript +[ + { + caption: "General", + properties: [ + { + key: "caption", + caption: "Graph caption", + description: "The caption of this graph" + } + ] + }, + { + caption: "Data", + properties: [ + { + key: "dataCaption", + caption: "Data caption", + description: "The caption of the data set" + }, + { + key: "dataPoints", + caption: "Data points", + description: "", + objects: [ + { + properties: [ + { + caption: "Data Point", + properties: [ + { key: "x", caption: "X value", description: "" }, + { key: "y", caption: "Y value", description: "" } + ] + } + ] + }, + { + properties: [ + { + caption: "Data Point", + properties: [ + { key: "x", caption: "X value", description: "" }, + { key: "y", caption: "Y value", description: "" } + ] + } + ] + }, + { + properties: [ + { + caption: "Data Point", + properties: [ + { key: "x", caption: "X value", description: "" }, + { key: "y", caption: "Y value", description: "" } + ] + } + ] + } + ] + } + ] + } +] +``` + +## Customizing Object Grids {#customize-object-grids} + +An object grid for object properties can be customized. To do this, the property needs to have `objectHeaders` configured, which will be used as column headers. Each object also needs to have `captions` configured for the grid to be filled. + +### Example + +If you wished to use data point structure detailed above to visualize geographic coordinates, you might want to add the suffixes `° N` and `° W` to the numeric **x** and **y** values so the grid will look like this (values below are purely hypothetical): + +| N Coordinate | W Coordinate | +| ------------ | ------------ | +| 51.9066° N | 4.4883° W | +| 42.3504° N | -71.0468° W | +| 51.5126° N | -0.1062° W | + +The following code example shows an object property configuration which uses object headers and captions for each object to achieve the table shown above: + +```typescript +{ + key: "dataPoints", + caption: "Data points", + description: "", + objectHeaders: ["N Coordinate", "W Coordinate"], // column headers + objects: [ + { + captions: [`${values.dataPoints[0].y}° N`, `${values.dataPoints[0].x}° W`], + properties: [ + { + caption: "Data Point", + properties: [ + { key: "y", caption: "Y value", description: "" }, + { key: "x", caption: "X value", description: "" } + ] + } + ] + }, + { + captions: [`${values.dataPoints[1].y}° N`, `${values.dataPoints[1].x}° W`], + properties: [ + { + caption: "Data Point", + properties: [ + { key: "y", caption: "X value", description: "" }, + { key: "x", caption: "X value", description: "" } + ] + } + ] + }, + { + captions: [`${values.dataPoints[2].y}° N`, `${values.dataPoints[2].x}° W`], + properties: [ + { + caption: "Data Point", + properties: [ + { key: "y", caption: "X value", description: "" }, + { key: "x", caption: "Y value", description: "" } + ] + } + ] + } + ] +} +``` + +## Customizing Validation Using Consistency Checks + +By default, Studio Pro will validate required properties. To add extra validations to the configured data, the module can export a `check` function. This function gets the values passed following the values API, and is expected to return an array of problems found: + +```typescript +function check(values: ValuesAPI): Problem[] +``` + +A `Problem` is an object defined by the following type: + +```typescript +type Problem = { + property?: string; // key of the property, at which the problem exists + severity?: "error" | "warning" | "deprecation"; // default = "error" + message: string; // description of the problem + url?: string; // link with more information about the problem +} +``` + +Any problem returned from this function will be shown in the [Errors](/refguide/errors-pane/) pane in Studio Pro. + +### Targeting a Property of a Sub-Object + +A property of the type `object` contains a list of objects with properties. In this case, it is possible to specify in which property of which object a problem occurred. This can be done by specifying the property as `//` where index is the 1-based index of the object list. + +#### Example + +For example, if an object-property `dataPoints` with the sub-properties `x` and `y` exists, and `y` should not be larger than 10, the following code will return the corresponding error: + +```typescript +function check(values) { + var problems = []; + values.dataPoints.forEach((p, i) => { + if (p.y > 10) { + problems.push({ + property: `dataPoints/${i + 1}/y`, + message: "y should not be larger than 10" + }); + } + }); + return problems; +} +``` + +## Customizing Page Explorer Caption + +The Page Explorer will normally use the type name of the custom widget as its caption. If a custom caption should be used, the module can export a `getCustomCaption` function. This function gets the values passed following the values API and the current platform: + +```typescript +function getCustomCaption(values: ValuesAPI, platform: "desktop" | "web"): string +``` + +If the caption is `null`, `undefined`, or not a string, then the default caption will be used. + +## Widget Preview in Structure Mode + +To configure the appearance of the custom widget in Studio Pro, export a `getPreview` function. This function receives three parameters: the first one contains the current values, the second one indicates whether dark mode is set, and the third parameter passes the current Studio Pro version. The function should return a preview properties object containing the configuration of the custom widget preview. + +Please note that the default colors will be automatically adjusted for dark mode (for example font color, border color, and more). However, the `isDarkMode` flag can be used when setting colors explicitly. + +To create a preview for different versions, you can use the third argument `version`. It contains the current Studio Pro version as an array of numbers in the format [`major`, `minor`, `build`], for example, `[9, 18, 0]`. + +The following describes the API for the preview properties object that the `getPreview` should return. + +The general element structure: + +```typescript +type BaseProps = { + type: string; // "Text" | "RowLayout" | "Image" …; + grow?: number; // optionally sets a growth factor if used in a layout (default = 1) +} +``` + +All types of preview properties share two common properties: `type` and `grow`: + +* `type` can be any of the preview types described below, such as `"Image"`, `"Text"`, or `"RowLayout"` +* `grow` is optional and only takes effect if the current element is a child of a row layout (see the [Row Layout](#row-layout) section for examples) + +The following elements extend the base preview props with properties native to their elements. For example, it could contain `content` for text elements, or `document` and `width` for image elements. The following element sections will list all available element types and their properties. + +### Image + +```typescript +type ImageProps = BaseProps & { + type: "Image"; + document?: string; // svg image + data?: string; // base64 image + property?: object; // widget image property object from Values API + width?: number; // sets a fixed maximum width + height?: number; // sets a fixed maximum height +} +``` + +Images properties can receive different types of input (but they always requires *either* a `document` or a `data`): + +* `document`: an SVG image string +* `data`: a base64 encoded image string +* `property`: the value of an image property. + * Please note when passing an image property, it will only show if a static image has been set (a `document` or `data` still needs to be passed as well, which will act as a fallback image when the property is empty or a dynamic image has been set) + +Additionally, a fixed `width` and `height` can be set. If not set, it will maximize to the available width. If the width and height are set to an aspect ratio that is different from the original image aspect ratio, it will show a section of the image so the image is not distorted. + +Here is an example of a circle SVG: + +```typescript +export const getPreview = (_values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => { + const mySvgImage = ` + + +`; + return { + type: "Image", + document: mySvgImage, + width: 200 // sets a maximum width of 200 + } +}; +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-image.png" alt="an svg image of a circle" width="200" class="no-border" >}} + +### Container + +```typescript +type ContainerProps = BaseProps & { + type: "Container"; + children: StructurePreviewProps[]; // any other preview element + borders?: boolean; // sets borders around the layout to visually group its children + borderRadius?: number; // integer. Can be used to create rounded borders + backgroundColor?: string; // HTML color, formatted #RRGGBB + borderWidth?: number; // sets the border width + padding?: number; // integer. adds padding around the container +} +``` + +Containers can be used to stack multiple elements vertically. These elements are passed as `children` as an array of props. The `borders` property can be used to set borders around the whole content to visually group them. + +Here is an example of two texts with borders around them: + +```typescript +export const getPreview = (_values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ( + { + type: "Container", + borders: true, + children: [ + { type: "Text", content: "I am on top" }, + { type: "Text", content: "I am on the bottom" } + ] + }); +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-container.png" alt="a bordered container with two texts" width="600" class="no-border" >}} + +### Row Layout {#row-layout} + +```typescript +type RowLayoutProps = ContainerProps & { + type: "RowLayout"; + columnSize?: "fixed" | "grow" // default is fixed +} +``` + +Row layouts are similar to a container, and can be used to render multiple elements horizontally next to each other. They have all the props that a container has, with the addition of a `columnSize`, which defines whether its children sizes are equal fixed weights or determined by their content (for more information, see the next section). + +#### Column Size + +##### Fixed (Default) + +When `columnSize` is not set (or set to `"fixed"`) all available space is split into fixed weights. It will then fit the child content into the column, rather than expanding and shrinking the column based on the content size. + +As an example, this is useful for creating grid-like structures. By default, all columns get the equal amount of space. However, if the children have a `grow` value set, this will be used to set proportional column sizes for the children. Children without a `grow` value automatically receive the value 1. + +As an example, consider this. The following code creates a row layout with four children. The first child (`Image`) takes the first half of the available space, and the other three children (`Texts`) share the other half. This can be achieved by simply setting the `grow` property of the first child to 3: + +```typescript +export const getPreview = (_values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ( + { + type: "RowLayout", + columnSize: "fixed", + children: [ + { type: "Image", data: mxLogo, grow: 3 }, + { type: "Text", fontSize: 20, content: "We share the" }, + { type: "Text", fontSize: 16, content: "right half of" }, + { type: "Text", fontSize: 12, content: "the row layout" } + ] + }); +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-row-layout-fixed.png" alt="a row layout with fixed column weights" width="1000" class="no-border" >}} + +##### Grow + +When the `columnSize` is set to `"grow"`, the column sizes are determined by the content. When there is leftover space, the space is distributed over all columns. To influence the relative amount of space into which a child grows, you can set a `grow` factor for each child. The column will then grow proportionally according to this factor. Children without a `grow` value automatically receive the value 1. + +If a layout has less space than the elements prefer, items are shrunk disproportionally to their `grow` factors (a high grow factor means a low shrink factor) until they reach their minimum sizes: + +* A `text` gets wrapped to become smaller +* An `image` does not shrink further than its original size unless manually set with the `width` property or when all elements have reached their minimum size + +Once all items have reached their minimum size, the layout will force smaller sizes proportionally to their `grow` value. + +Please note that forcing items smaller than they require works for images, but might cause unexpected behavior with other elements. + +Here is an example to show how grow factors behave: + +```typescript +export const getPreview = (_values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ( + { + type: "RowLayout", + columnSize: "grow", + children: [ + { + type: "Container", + grow: 0, + borders: true, + backgroundColor: "#F4FFB0", + children: [{ type: "Text", content: "Grow 0", fontSize: 20 }] + }, + { + type: "Container", + borders: true, + backgroundColor: "#E6FFB0", + children: [{ type: "Text", content: "Grow 1", fontSize: 20 }] + }, + { + type: "Container", + grow: 2, + borders: true, + backgroundColor: "#B0C0FF", + children: [{ type: "Text", content: "Grow 2", fontSize: 20 }] + } + ] + }); +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-row-layout-grow.png" alt="a row layout with different grow factors" width="1000" class="no-border" >}} + +##### Example + +Here is an example of a button to show how to center items using row layouts: + +```typescript +export const getPreview = (_values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ( + { + type: "RowLayout", + columnSize: "grow", + borders: true, + borderRadius: 20, + backgroundColor: "#2A2C96", + children: [ + { + type: "Container", // fills space on the left + }, + { + type: "Container", + grow: 0, // ensures that it only takes necessary space + padding: 10, + children: [ + { type: "Text", content: "A button", fontColor: "#FFF", fontSize: 20 } + ] + }, + { + type: "Container", // fills space on the right + } + ] + }); +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-row-layout-grow-2.png" alt="structure mode preview of a bordered container with two texts" width="600" class="no-border" >}} + +### Text + +```typescript +type TextProps = BaseProps & { + type: "Text"; + content: string; // text that should be shown + fontSize?: number; // sets the font size + fontColor?: string; // HTML color, formatted #RRGGBB + bold?: boolean; + italic?: boolean; +} +``` + +The text to be displayed must be passed as `content`. You can optionally set a `fontSize`. Please note that only integers are supported as font size. + +Here is an example: + +```typescript +export const getPreview = (values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ( + { + type: "Text", + content: values.myTextProp, // set displayed text to the value of myTextProp + }); +``` + +### Drop Zones + +```typescript +type DropZoneProps = BaseProps & { + type: "DropZone"; + property: object; // widgets property object from Values API + placeholder: string; // text to be shown inside the dropzone when empty + showDataSourceHeader: bool?; // true by default. Toggles whether to show a header containing information about the datasource +} +``` + +The drop zone preview type can be used to add drop zones to the widget preview. It requires a widget property of type `widgets` to be able to store the information about the containing widgets. If the property has a data source, a header will be shown inside the dropzone containing information about the data source. This header is optional and can be hidden by setting `showDataSourceHeader` to `false`. + +To configure a drop zone, the widgets property object (which can be obtained directly from the [Values API](/apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis/#values)) needs to be passed as `property`, as the following example shows: + +```typescript +exports.getPreview = (values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ({ + type: "Container", + borders: true, + children: [ + { + type: "Text", + content: "This widget acts as a container for other widgets" + }, + { + type: "DropZone", + property: values.myWidgetsProp + placeholder: "Drop your widgets here!" + } + ] +}) +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-drop-zone.png" alt="a container with a dropzone" width="600" class="no-border" >}} + +### Selectable + +```typescript +type SelectableProps = BaseProps & { + type: "Selectable"; + object: object; // object property instance from the Value API + child: StructurePreviewProps; // any type of preview property to visualize the object instance +} +``` + +The selectable preview type can be used to make an instance of an object list selectable. If an object instance is made selectable, it will behave similar to a widget. Its properties will be shown in the `Properties` section and can also be edited in a pop-up by double-clicking the section that is visualized by the `child` properties. Note that this only works in combination with a property of type `object`. + +To configure a selectable, the object from the [Value API](/apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis/#values) needs to be passed as `object`, and the preview properties to visualize the object as `child`. + +The following example shows how to render a container with a list of selectable objects. In this case, each object is shown as a text with its caption: + +```typescript +export function getPreview(values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) { + const container: ContainerProps = { + type: "Container", + borders: true, + children: [ + { type: "Text", fontSize: 18, content: "List with selectable elements" } + ], + }; + + for (const item of values.myObjectProp) { + container.children!.push({ + type: "Selectable", + object: item, + child: { + type: "Text", + fontColor: "#2A2C96", + content: item.caption + }, + }); + } + return container; +} +``` + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-selectable.png" alt="a list of selectable text elements" width="600" class="no-border" >}} + +### Datasource + +```typescript +type DatasourceProps = BaseProps & { + type: "Datasource"; + property: Nullable; // datasource property object from Values API + child?: StructurePreviewProps; // any type of preview property component (optional) +} +``` + +The **datasource** preview type can be used when developing a widget with a data source. Using it will render a container with a data source header, similar to other data widgets such as data views or list views. For example, the following will render a data source container with a drop-zone: + +```typescript + exports.getPreview = (values: WidgetPreviewProps, _isDarkMode: boolean, _version: number[]) => ({ + type: "Datasource", + property: values.myDatasourceProp, // pass the datasource property + child: { + type: "DropZone", + property: values.myWidgetsProp + } + }) +``` + +Here is a preview of a **datasource** component containing a drop-zone with two text boxes: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/structure-preview-example-datasource.png" alt="a widget with a datasource" width="400" class="no-border" >}} diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-native-dependencies.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-native-dependencies.md new file mode 100644 index 00000000000..d13e150ff4a --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-native-dependencies.md @@ -0,0 +1,66 @@ +--- +title: "Declaring Native Dependencies" +url: /apidocs-mxsdk/apidocs/pluggable-widgets-native-dependencies-10/ +description: A guide for understanding native dependencies for pluggable widgets and JavaScript actions in Mx10. +weight: 40 +--- + +## Introduction + +While developing pluggable widgets and JavaScript actions it is essential to reuse existing modules and libraries from the JavaScript ecosystem. Mendix empowers widget developers with [Pluggable Widgets Tools](https://github.com/mendix/widgets-resources/tree/master/packages/tools/pluggable-widgets-tools) to help you create, develop, and ship pluggable widgets. These tools do the power lifting of linking and embedding third-party dependencies into pluggable widgets' code. The tooling also provides information about Android- and iOS-specific setup parts of some libraries to Mendix native mobile apps. Read on to learn more about how pluggable widgets communicate native dependencies to the Mendix native ecosystem. + +While this tooling exists for pluggable widgets, some manual work has to be done for JavaScript actions in order to use libraries targeting `react-native` Android- and iOS-specific setups. Read this page if you want to use such libraries in your JavaScript actions. + +## Declaration File {#declaration-file} + +The declaration file is a *.json* file which contains information about the specific setup required by a pluggable widget or a JavaScript action. + +Where you place the file depends on your situation: + +* For JavaScript actions, declare in the *.json* file +* For widgets, if you are using the latest **pluggable-widgets-tools** they will collect and create the declaration file automatically +* If you are creating a widget on your own, create a *.json* file which has the same name as your widget as listed in its *.mpk* + +### Naming Conventions + +For pluggable widgets, the declaration file should be named after the [Widget Definition XML File](/apidocs-mxsdk/apidocs/pluggable-widgets/#widget-definition), but should use a *.json* extension. + +For JavaScript actions, the declaration file should be named after the name of a `.js` file of the action, but should use a *.json* extension. + +### File Format + +The file is a *.json* file of one object of which uses the following format: + +```json +{ + "nativeDependencies": { + "dependency-name": "1.2.3" + } +} +``` + +Only the `nativeDependencies` key is allowed in that file. This field is used to declare the native dependencies of the pluggable widget or JavaScript action that this file belongs to. + +## Native Dependencies + +In order to declare native dependencies needed for a pluggable widget or a JavaScript action, entries are added to the JSON object under the `nativeDependencies` key. The following example specifies two dependencies with their corresponding versions: + +```json +{ + "nativeDependencies": { + "@react-native-community/netinfo": "5.9.10", + "react-native-image-picker": "3.1.4" + } +} +``` + +As you can see above, the key of the entry is a name of the dependency and the value is a version of a dependency needed. Note that `semver` is not supported; an exact version must be specified. + +## Conflict Checking + +It is not possible to include different versions of the same native dependency in one app. Therefore, when different components in an app use the same native dependency Studio Pro begins a conflict check. It makes sure there is no mismatch between versions required by different components. If version conflicts are detected, they are reported. + +## Read More + +* [Pluggable Widget API Documentation](/apidocs-mxsdk/apidocs/pluggable-widgets/) +* [Build JavaScript Actions for Native Mobile](/howto/extensibility/create-native-javascript-action/) diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-property-types.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-property-types.md new file mode 100644 index 00000000000..caa2b15fa39 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-property-types.md @@ -0,0 +1,921 @@ +--- +title: "Property Types" +url: /apidocs-mxsdk/apidocs/pluggable-widgets-property-types-10/ +description: A guide for understanding pluggable widgets' property types in Mx10. +weight: 10 +--- + +## Introduction + +In order to be configurable, pluggable widgets use a [widget properties definition](/apidocs-mxsdk/apidocs/pluggable-widgets/#properties-definition) which describes the properties available to pluggable widgets. To see examples of pluggable widgets in action, see [How To Build Pluggable Widgets](/howto/extensibility/pluggable-widgets/). + +The common structure of a property definition is as follows: + +```xml + + My Property + This is my property + +``` + +### XML Attributes + +#### Key (required) {#key} + +This defines the prop `key` in the client component props which are supplied to the widget client component. Each property must have a unique `key` which can contain letters of all cases, digits, or underscores. However, a `key` attribute cannot *start* with a digit. + +#### Type (required) + +This defines a property's type. A `type` must be one of the following: + +* Static Types + * [string](#string) + * [boolean](#boolean) + * [integer](#integer) + * [decimal](#decimal) + * [enumeration](#enumeration) +* Component Types + * [icon](#icon) + * [image](#image) + * [widgets](#widgets) +* Dynamic Types + * [expression](#expression) + * [textTemplate](#texttemplate) + * [action](#action) + * [attribute](#attribute) + * [association](#association) + * [object](#object) + * [file](#file) + * [datasource](#datasource) + * [selection](#selection) + +### XML Elements + +`` (required) — This defines the property name visible for the user (not the end-user) while configuring the widget in Studio Pro. + +`` (required) — This is a description which explains a property's purpose. + +## Static Types + +Static types are made to pass values configured in Studio Pro to the widget. They do not depend on any dynamic data. Static properties are passed to the widget client component as simple primitive values. + +### String {#string} + +The string property type is represented as a simple text input in Studio Pro. It is passed as a `string` prop to a client component. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|-----------------------------------------------------------------------| +| `type` | Yes | String | Must be `string` | +| `key` | Yes | String | See [key](#key) | +| `defaultValue` | No | String | Default value for the property | +| `multiline` | No | Boolean | `true` to enable multiline input, `false` otherwise | +| `required` | No | Boolean | Whether the property must be specified by the user, `true` by default | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + My string + My string setting + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/string.png" class="no-border" >}} + +When the property is defined as follows: + +```xml + + My string multiline + My string multiline setting + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/string-multiline.png" class="no-border" >}} + +### Boolean {#boolean} + +Properties of type Boolean are represented as a toggle in Studio Pro. They are passed as `boolean` props to a client component. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +| - | - | - | - | +| `type` | Yes | String | Must be `boolean` | +| `key` | Yes | String | See [key](#key) | +| `defaultValue` | Yes | Boolean | Default value for the property, `true` or `false` | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + My boolean + My boolean setting + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/boolean.png" class="no-border" >}} + +### Integer {#integer} + +Integer is represented as a number input in Studio Pro. It is passed as a `number` prop to a client component. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|--------------------------------| +| `type` | Yes | String | Must be `integer` | +| `key` | Yes | String | See [key](#key) | +| `defaultValue` | Yes | Integer | Default value for the property | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + My integer + My integer setting + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/integer.png" class="no-border" >}} + +### Decimal {#decimal} + +Properties of type decimal are represented as a number input in Studio Pro. They are passed as a `Big` prop to a client component. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|--------------------------------| +| `type` | Yes | String | Must be `decimal` | +| `key` | Yes | String | See [key](#key) | +| `defaultValue` | Yes | Integer | Default value for the property | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + My decimal + My decimal setting + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/decimal.png" alt="decimal" class="no-border" >}} + +### Enumeration {#enumeration} + +The enumeration property type allows a user to select one out of multiple options defined in the XML. The `key` of a selected enumeration element is passed as `string` prop to a client component. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|--------------------------------| +| `type` | Yes | String | Must be `enumeration` | +| `key` | Yes | String | See [key](#key) | +| `defaultValue` | Yes | Integer | Default value for the property | + +#### XML Elements + +`` (required) — One `` element must be declared with multiple `` elements inside in order to define possible enumeration values. A `key` attribute is required for every enumeration value as well as a caption. Enter enumeration values like this: + +```xml +My enum option caption +``` + +The `key` of a selected element will be passed to the client component. `key` should not be changed since it is used to identify options used in an app. + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + My enumeration + My enumeration setting + + Red + Green + Blue + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/enumeration.png" class="no-border" >}} + +## Component Types + +### Icon {#icon} + +Properties of type icon allows a user to configure an icon similar to one used by a [button](/refguide/button-properties/#icon). It is passed as `DynamicValue` prop to a client component. For more information, see the [IconValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#icon-value) section of *Client APIs Available to Pluggable Widgets*. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|------------|----------|----------------|-----------------------------------------------------------------------| +| `type` | Yes | String | Must be `icon` | +| `key` | Yes | String | See [key](#key) | +| `required` | No | Boolean | Whether the property must be specified by the user, `true` by default | + +#### Studio Pro UI + +When the component is defined as follows: + +```xml + + Icon + Card icon + +``` + +Then the Studio Pro UI for the component appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/icon.png" class="no-border" >}} + +### Image {#image} + +Image allows a user to configure a static image from an [image collection](/refguide/image-collection/). It also allows a user to configure an image from an object that is a specialization of **System.Image**. It is passed as an `DynamicValue` prop to a client component (for more information, see the [ImageValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#imagevalue) section of *Client APIs Available to Pluggable Widgets*). See the [Images Reference Guide](/refguide/images/) for more information about supported image formats. + +{{% alert color="warning" %}} +GIF images are not supported in native mobile apps on Android devices. +{{% /alert %}} + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|------------|----------|----------------|-----------------------------------------------------------------------| +| `type` | Yes | String | Must be `image` | +| `key` | Yes | String | See [key](#key) | +| `required` | No | Boolean | Whether the property must be specified by the user, `true` by default | + +#### Studio Pro UI + +When the component is defined as follows: + +```xml + + Background Image + Image shown blurred in a background + +``` + +Then the Studio Pro UI for the component appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/image.png" class="no-border" >}} + +### Widgets {#widgets} + +The widgets property allows a user to place multiple widgets inside a pluggable widget, similar to the content of a [container](/refguide/container/) widget. It is passed as a `ReactNode` prop to a client component if a `dataSource` attribute is not specified, otherwise it is passed as a [`ListWidgetValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listwidgetvalue). For more information, see the [Datasource](#datasource) section below. + +{{% alert color="warning" %}} +Some widgets are not yet supported inside pluggable widgets. Placing unsupported widgets inside a pluggable widget results in a consistency error in Studio Pro. +{{% /alert %}} + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|--------------|----------|----------------|------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `widgets` | +| `key` | Yes | String | See [key](#key) | +| `dataSource` | No | Property Path | Specifies the path to a [`datasource`](#datasource) property linked to this `widgets` property | +| `required` | No | Boolean | Whether a user must provide at least one widget, `true` by default | + +#### Studio Pro UI + +When the component is defined without the `dataSource` attribute as follows: + +```xml + + Content + Content of a box + +``` + +then the Studio Pro UI for the component appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/widgets.png" alt="studio pro ui" class="no-border" >}} + +#### Using the DataSource Attribute + +When the component is defined with the `dataSource` attribute, assuming `myDataSource` is key of a [`datasource`](#datasource) property defined elsewhere for this widget: + +```xml + + Content + Widgets using data source + +``` + +then the Studio Pro UI for the component appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/widgets_with_ds.png" alt="studio pro ui" class="no-border" >}} + +## Dynamic Types + +### Expression {#expression} + +The expression property allows a user to configure an [expression](/refguide/expressions/). + +If a `dataSource` attribute is not specified, the client will receive a `DynamicValue` where `T` depends on the expression's return type. + +When a `dataSource` attribute is specified and configured by the user, it is passed as a [`ListExpressionValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listexpressionvalue) where `T` depends on the expression's return type. For more information, see the [Datasource](#datasource) section below. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|---------------------|-------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `expression` | +| `key` | Yes | String | See [key](#key) | +| `defaultValue` | No | String (Expression) | Default value for the property | +| `required` | No | Boolean | Whether the property must be specified by the user, `true` by default | +| `dataSource` | No | Property Path | Specifies the path to a [`datasource`](#datasource) property linked to this expression property | + +#### XML Elements + +`` (required) — An expression property must contain a `` element in order to define the return type of the expression. The Mendix Platform will ensure the that configured expression returns the correct data type. + +The return type of the expression must be defined using either the `type` or the `assignableTo` attribute. It is not allowed to specify both. + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|------------------------------------------------------------------------------------------------------------------| +| `type` | No | String | A fixed return type, which must be one of the supported fixed return types | +| `assignableTo` | No | Property Path | Specifies the path to an [`attribute`](#attribute) property which will determine the return type when configured | + +##### Fixed Return Type + +You can set a fixed return type for your expression property with one of the supported types from below. + +| Supported Return Types | Corresponding Types Client Components Receive | +|------------------------|-----------------------------------------------------------------------------------------| +| `Boolean` | `DynamicValue` | +| `DateTime` | `DynamicValue` | +| `Decimal` | `DynamicValue` | +| `Integer` | `DynamicValue` | +| `String` | `DynamicValue` | + +##### Return Type Assignable to an Attribute + +You can use `assignableTo` to specify that the return type of the expression property should depend on the attribute property with the given property path. This means that the value of the expression will be assignable to the attribute configured for that attribute property (using [`setValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#editable-value)). + +The client component will receive a `DynamicValue` where `T` depends on the possible types of the target attribute. If the attribute property allows for more than one type, the type of the actual value depends on the attribute that has been configured. + +For example, when properties are defined as follows: + +```xml + + My string + My string setting + + + + + +``` + +```xml + + My string + My string setting + + +``` + +The client component will receive a `myExpression` prop of type `DynamicValue`. + +This is a union type of all possible value types for the expression. The actual type of the value depends on the attribute configured for the `myAttribute` property. For an attribute of type `String`, the value will be a `string`; otherwise, it will be a `boolean`. + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + Color + Progress bar CSS color + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/expression.png" class="no-border" >}} + +### TextTemplate {#texttemplate} + +The TextTemplate property allows a user to configure a translatable text template similar to the [Caption](/refguide/text/#caption) of a text widget. + +If a `dataSource` attribute is not specified, the interpolated string will be passed to the client component as `DynamicValue`. + +When a `dataSource` attribute is specified and configured by the user, it is passed as a [`ListExpressionValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listexpressionvalue). For more information, see the [Datasource](#datasource) section below. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|--------------|----------|----------------|----------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `textTemplate` | +| `key` | Yes | String | See [key](#key) | +| `multiline` | No | Boolean | `true` to enable multiline input, `false` otherwise | +| `required` | No | Boolean | Whether the property must be specified by the user, `true` by default | +| `dataSource` | No | Property Path | Specifies the path to a [`datasource`](#datasource) property linked to this text template property | + +#### XML Elements + +`` — Allows a user to set a default value for text templates for different languages using `` elements with a `lang` attribute representing [ISO 639](https://en.wikipedia.org/wiki/ISO_639) code of the language. Available languages are listed in the [Languages Tab](/refguide/app-settings/#languages-tab) in Studio Pro. + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + Input title + Title for the color input + + Color + Kleur + Колір + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/text.png" class="no-border" >}} + +### Action {#action} + +{{% alert color="info" %}} +The `defaultType` and `defaultValue` attributes for Action were introduced in Mendix [10.15](/releasenotes/studio-pro/10.15/). +{{% /alert %}} + +The action property type allows a user to configure an action which can do things like call nanoflows, save changes, and open pages. + +If a `dataSource` attribute is not specified, the client will receive an `ActionValue` representing the action or `undefined` if the **Do nothing** action was selected. + +When a `dataSource` attribute is specified and configured by the user, it is passed as a [`ListActionValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listactionvalue). For more information, see the [Datasource](#datasource) section below. + +#### XML Attributes {#xml-attributes} + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|---------------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `action` | +| `key` | Yes | String | See [key](#key) | +| `dataSource` | No | Property Path | Specifies path to a [`datasource`](#datasource) property linked to this action property | +| `defaultValue` | No | String | Default value for the property, the format should be `.` | +| `defaultType` | No | String | Default type for the property, supported values are `None`, `OpenPage`, `CallNanoflow`, `CallMicroflow` | + +#### XML Elements {#action-xml-elements} + +`` — Defines variables a widget provides when calling [execute() on an ActionValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#execute). The variables are made available in Studio Pro when configuring [Call a Microflow](/refguide/on-click-event/#call-microflow) and [Call a Nanoflow](/refguide/on-click-event/#call-nanoflow) actions. + +`` (required one or more) — Represents a primitive value provided by the widget as an argument when calling `ActionValue.execute()`. The variable is defined by the following attributes: + +* `key` (required) — The identifier of the variable used in Studio Pro and the Pluggable Widgets API. +* `type` (required) — The type of the value that the variable represents. Supported types and their corresponding Typescript type are listed in the table below. +* `caption` (required) — A short description of the variable that is displayed in Studio Pro. + +| Action Variable Type | Client Type | +| -------------------- | --------- | +| `String` | `string` | +| `Integer` | `Big` | +| `Decimal` | `Big` | +| `DateTime` | `Date` | +| `Boolean` | `boolean` | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + On click + Action to be performed when button is clicked + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/action.png" class="no-border" >}} + +When the action exposes variables with the following XML: + +```xml + + On click + Action to be performed when button is clicked + + + + +``` + +The variable appears in the UI like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/action-variable.png" class="no-border" >}} + +### Attribute {#attribute} + +The attribute property type allows a widget to work directly with entities' attributes, both reading and writing attributes. Depending on the widget's purposes, a widget should define attribute types it supports. + +If a `dataSource` attribute is not specified, the client will receive an `EditableValue` where `T` depends on a configured ``. For more information, see the [EditableValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#editable-value) section of *Client APIs Available to Pluggable Widgets*. + +When a `dataSource` attribute is specified and configured by the user, it is passed as a [`ListAttributeValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listattributevalue). For more information, see the [Datasource](#datasource) section below. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|--------------|----------|----------------|----------------------------------------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `attribute` | +| `key` | Yes | String | See [key](#key) | +| `onChange` | No | Property Path | The path to an [`action`](#action) property that will be run by the Mendix Platform when the value is changed by the widget | +| `required` | No | Boolean | Decides if the property must be specified by the user, `true` by default | +| `dataSource` | No | Property Path | Specifies the path to a [`datasource`](#datasource) property linked to this attribute property | +| `setLabel` | No | Boolean | `true` to enable setting [`Label`](#setLabel) value automatically with configured attribute, false `otherwise` | + +#### XML Elements + +`` (required) — This element encapsulates `` elements which declare supported attribute types available while configuring the attribute property in Studio Pro. + +`` (required one or more) — this element defines the allowed attribute type in the `name` attribute. + +| Supported Attribute Types | Corresponding Types Client Components Receive | +|---------------------------|-----------------------------------------------| +| `AutoNumber` | `EditableValue` | +| `Binary` | `EditableValue` | +| `Boolean` | `EditableValue` | +| `DateTime` | `EditableValue` | +| `Enum` | `EditableValue` | +| `HashString` | `EditableValue` | +| `Integer` | `EditableValue` | +| `Long` | `EditableValue` | +| `String` | `EditableValue` | +| `Decimal` | `EditableValue` | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + Percentage + Progress percentage + + + + + + + + On change + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/attribute.png" class="no-border" >}} + +### Association {#association} + +The association property type allows a widget to work directly with both reading and writing associations between entities. Depending on the widget's purposes, a widget should define association types it supports. + +If a `dataSource` attribute is not specified the client will receive a `ReferenceValue` for references (singular references), a `ReferenceSetValue` for reference sets (multiple references), or a union of them. For more information, see the [ModifiableValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#modifiable-value) section of *Client APIs Available to Pluggable Widgets*. + +When a `dataSource` attribute is specified and configured by the user, it is passed as a [`ListReferenceValue` or `ListReferenceSetValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listassociationvalue) depending on the configuration of the property. For more information, see the [Datasource](#datasource) section below. + +#### XML Attributes {#xml-attributes} + +| Attribute | Required | Attribute Type | Description | +|---------------------|----------|----------------|----------------------------------------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `association` | +| `key` | Yes | String | See [key](#key) | +| `onChange` | No | Property Path | The path to an [`action`](#action) property that will be run by the Mendix Platform when the value is changed by the widget | +| `required` | No | Boolean | Decides if the property must be specified by the user, `true` by default | +| `selectableObjects` | Yes | Property Path | Specifies the path to a [`datasource`](#datasource) property that will provide selectable objects for the association | +| `dataSource` | No | Property Path | Specifies the path to a [`datasource`](#datasource) property linked to this association property | +| `setLabel` | No | Boolean | `true` to enable setting [`Label`](#setLabel) value automatically with configured entity, false `otherwise` | + +#### XML Elements + +`` (required) — This element encapsulates `` elements which declare supported association types available while configuring the association property in Studio Pro. + +`` (required one or more) — this element defines the allowed association type in the `name` attribute. + +| Supported Attribute Types | Corresponding Types Client Components Receive | +|---------------------------|-----------------------------------------------| +| `Reference` | `ReferenceValue` | +| `ReferenceSet` | `ReferenceSetValue` | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + Reference + Reference + + + + + + + + Selectable objects + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/association.png" class="no-border" >}} + +### Object {#object} + +The object property type allows to create an arbitrary list of properties. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|------------|----------|----------------|--------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `object` | +| `key` | Yes | String | See [key](#key) | +| `isList` | Yes | Boolean | Must be `true` | +| `required` | No | Boolean | This decides if the user is required to specify items in the list, `true` by default | + +#### XML Elements + +`` (required) — This encapsulates the list or properties to be configured. For more information on property groups, see the [Property Groups](/apidocs-mxsdk/apidocs/pluggable-widgets/#property-groups) section of *Pluggable Widgets API*. Properties must be grouped by `` elements. Nested object properties are not supported. + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + My object list + + + + + My boolean + My boolean setting + + + My action + My action setting + + + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/object.png" >}} + +### File {#file} + +The file property type allows a user to configure a file from an object that is a specialization of **System.File**. It is passed as a [`DynamicValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#filevalue) prop to a client component. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|-----------|----------|----------------|-----------------| +| `type` | Yes | String | Must be `file` | +| `key` | Yes | String | See [key](#key) | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + + File + Sample text file + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/file.png" >}} + +### Datasource {#datasource} + +The datasource property allows widgets to work with object lists. The client component will receive value prop of type [`ListValue`](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values/#listvalue) and may be used with [`action`](#action), [`attribute`](#attribute), [`association`](#association), [`expression`](#expression), [`text template`](#texttemplate), and [`widgets`](#widgets) properties. See [Data Sources](/refguide/data-sources/#list-widgets) for available data source types. + +If no data source has been configured by the user, any properties that are linked to the datasource property are automatically omitted from the props passed to the client component (even if they are marked as required). + +{{% alert color="warning" %}} +Only list datasources are supported, therefore specifying `isList="true"` is required. +{{% /alert %}} + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|----------------|------------------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `datasource` | +| `key` | Yes | String | See [key](#key) | +| `isList` | Yes | Boolean | Must be `true` | +| `required` | No | Boolean | This decides if the user is required to specify a datasource, `true` by default | +| `defaultType` | No | String | Default type for the property, supported values are `Database`, `Microflow`, `Nanoflow`, and `Association` | +| `defaultValue` | No | String | Default value for the property, see [Default Data Sources](#data-source-defaults) | + +##### Data Source Defaults {#data-source-defaults} + +{{% alert color="info" %}} +The `defaultType` and `defaultValue` attributes for datasources were introduced in Mendix [10.16](/releasenotes/studio-pro/10.16/). +{{% /alert %}} + +You can use the `defaultType` and `defaultValue` attributes to configure default data sources for your widget. Unless overridden in Studio Pro, the widget will attempt to configure the data source according to its defaults. Both attributes need to be set for the defaults to be applied. + +The format of `defaultValue` depends on the chosen `defaultType`: + +| Data source type | Format | Example | +|--------------------------|-------------|-----------------------------------------------------------------------| +| `Database` `Association` | Entity Path | `ModuleName.EntityName` or `ModuleName.A/ModuleName.A_B/ModuleName.B` | +| `Microflow` `Nanoflow` | Document ID | `ModuleName.DocumentName` | + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + Data source + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/datasource.png" class="no-border" >}} + +### Selection {#selection} + +{{% alert color="info" %}} +The property type was introduced in Mendix [10.7](/releasenotes/studio-pro/10.7/). +{{% /alert %}} + +The selection property allows a widget to read and set a selection that can be used in actions, expressions, or a `Listen to` data source of a data view. + +#### XML Attributes + +| Attribute | Required | Attribute Type | Description | +|----------------|----------|---------------------|---------------------------------------------------------------------------------------------------------------------------------| +| `type` | Yes | String | Must be `selection` | +| `key` | Yes | String | See [key](#key) | +| `dataSource` | Yes | Property Path | Specifies the path to a [`datasource`](#datasource) property linked to this selection property | +| `defaultValue` | No | String (Expression) | Default value for the property | +| `onChange` | No | Property Path | The path to an [`action`](#action) property that will be run by the Mendix Platform when the selection is changed by the widget | + +#### XML Elements + +`` (required) — This element encapsulates `` elements which declare supported selection types available while configuring the selection property in Studio Pro. + +`` (required one or more) — This element defines the selection type in the `name` attribute. + +| Supported Selection Types | Corresponding Types Client Components Receive | +|---------------------------|-----------------------------------------------| +| `None` | `undefined` | +| `Single` | `SelectionSingleValue` | +| `Multi` | `SelectionMultiValue` | + +For more information, see the [SelectionValue](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#selection-value) section of *Client APIs Available to Pluggable Widgets*. + +#### Studio Pro UI + +When the property is defined as follows: + +```xml + + Selection + + + + + + + +``` + +Then the Studio Pro UI for the property appears like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-property-types/selection.png" >}} + +## System Properties {#system-properties} + +System properties is a way for a pluggable widget to adopt extended widget functionality provided by Mendix Platform. System properties should be defined as `` elements. The only property XML attribute `` requires is `key` attribute, which defines a system property's type. The following values are allowed: + +* `Label` +* `Name` +* `TabIndex` +* `Visibility` +* `Editability` + +### Label {#label} + +Label property allows a pluggable widget to have labeling functionality similar to a [core input widget](/refguide/text-box/#label). This allows a user to set a label, a label position, and a label width. If a widget has a label configured, its client component will automatically be wrapped into a correct markup. + +```xml + +``` + +#### setLabel {#setLabel} + +{{% alert color="info" %}} +The `setLabel` attribute was introduced in Mendix [10.5](/releasenotes/studio-pro/10.5/). +{{% /alert %}} + +You can use `setLabel` to specify which properties can be used to set the `Label` property value. + +Configuring the value of a property with the `setLabel` attribute will automatically update the value of `Label`. + +Only attribute and association properties can use the `setLabel` attribute. + +The `Label` value is set only if it lacks a non-default value when you set it. If a property become hidden, the `Label` value is reverted back to default. More than one property can set the label. However if multiple properties with the `setLabel` attribute are visible simultaneously, the first one updated sets the label. For example, when properties are defined as follows: + +```xml + + My string + My string setting + + + + + + + Reference + Reference + + + + + + + Selectable objects + + +``` + +Then the `Label` property will be set by the first property configured. + +### Name {#name} + +Every widget have a name by default. This property can be used to control position of the widget name input. If this property is not specified, input will be placed in **Common** tab. A widget’s name is also used for locating it during [automated tests](/howto/integration/selenium-support/). For that purpose in web apps, a widget name is automatically appended to a `class` prop a component receives, and in native mobile apps is passed as a separate `name` prop. + +```xml + +``` + +### TabIndex {#tabindex} + +The TabIndex property allows pluggable widgets to implement the **Tab index** setting similar to a [core input widget](/refguide/common-widget-properties/#tab-index). Every selectable or input-like widget should opt for this to provide a consistent developing experience and an accessible app for an end-user. A widget’s tab index, when it is not zero, is passed to a client component in a `tabIndex` prop. + +```xml + +``` + +### Visibility {#visibility} + +Every pluggable widget can be [conditionally hidden](/refguide/common-widget-properties/#visibility-properties). This property can be used to control a position of the widget visibility inputs. + +```xml + +``` + +### Editability {#editability} + +The editability property allows a pluggable widget to have an editable configuration similar to a [core input widget](/refguide/text-box/#editability). When a widget is marked as read-only or conditionally editable with condition being false, all [editable values](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/#editable-value) its client component receives will have `readOnly` flag. + +```xml + +``` + +## Read More + +* [Pluggable Widgets API](/apidocs-mxsdk/apidocs/pluggable-widgets/) +* [Client APIs Available to Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/) +* [Build Pluggable Widgets](/howto/extensibility/pluggable-widgets/) diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-studio-apis.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-studio-apis.md new file mode 100644 index 00000000000..5813c059da5 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-10/pluggable-widgets/pluggable-widgets-studio-apis.md @@ -0,0 +1,295 @@ +--- +title: "Preview Appearance APIs" +linktitle: "Preview Appearance APIs" +url: /apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis-10/ +description: A guide for understanding the APIs which influence pluggable widget preview appearances in Mx10. +weight: 30 +--- + +## Introduction + +This guide explains the APIs offered by Mendix Studio Pro so you can build better pluggable widgets. Specifically, you can use these APIs and modules to alter pluggable widgets' preview appearances while working in Studio Pro's **Design mode**. To learn about creating a custom preview in **Structure mode**, add custom consistency checks, or conditionally hide widget properties, read the [Configuration Module API for Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-config-api/). + +Lastly, [Client APIs Available to Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/) is meant for pluggable widget development once your app is running in the client. This guide's APIs are available in Mendix 8.0.0 and higher. + +## Values API {#values} + +The values API passes the values configured for a pluggable widget's properties. These values will be passed in a JavaScript object, where the property's `key` is used as the object property. + +Here is an example of such an object: + +```javascript +{ + stringProp: "Some value", + intProp: 42 +} +``` + +### Static Properties + +Static property types are exposed with their configured value as a JavaScript value: + +| Plugin Widget Type | JavaScript Type | +| ------------------ | --------------- | +| `string` | `string` | +| `boolean` | `boolean` | +| `integer` | `number` | +| `decimal` | `number` | +| `enumeration` | `string` | + +For `enumeration` properties, the currently selected option's `key` will be used as the value. + +### Icon {#icon} + +This property appears as follows: + +```typescript +type GlyphIcon = { type: "glyph"; iconClass: string; } +type ImageIcon = { type: "image"; imageUrl: string; } +type Icon = { type: "icon"; iconClass: string; } + +type IconProperty = null | GlyphIcon | ImageIcon | Icon; +``` + +Icon properties are exposed objects containing a `type` field that is `"glyph"` if a glyphicon is selected, `"image"` if an image is selected, `"icon"` if an icon from an icon collection is selected, or `null` if no icon is selected at all. + +For the `"glyph"` type, `iconClass` is available. It contains the class to apply on a `glyphicon` element to display the correct icon. It will be an empty string value if no icon has been selected. + +For the `"image"` type, `imageUrl` is available. It represents a URL from which your selected image can be reached by Studio Pro's **Design mode**. It will be an empty string value if no image has been selected. + +For the `"icon"` type, `iconClass` is available. It contains the classes to apply to an element to display the correct icon. This element does not need to have the `glyphicon` class. It will be an empty string value if no icon has been selected. + +### Image + +This property appears as follows: + +```typescript +type StaticImage = { type: "static"; imageUrl: string; }; +type DynamicImage = { type: "dynamic"; entity: string; }; + +type ImageProperty = null | StaticImage | DynamicImage; +``` + +Image properties are exposed objects containing a `type` field that is `"static"` if a static image is selected, `"dynamic"` if an entity is selected, or `null` if no image is selected at all. + +For the `"static"` type, `imageUrl` is available. It represents a URL from which your selected image can be reached by Studio Pro's **Design mode**. It will be an empty string value if no image has been selected. + +For the `"dynamic"` type, `entity` is available. It represents the entity where the selected image's data is stored. It will be an empty string value if no entity has been selected. + +### Widgets {#widgets} + +This property appears as follows: + +```typescript +type WidgetsProperty = { + widgetCount: number; + renderer: React.ComponentType<{caption?: string}>; +} +``` + +This property is exposed as an object containing the following properties: + +* `widgetCount`: The number of immediate child widgets configured +* `renderer`: A React component allowing rendering of the child widgets in the preview + * The renderer component has an extra property called `caption` which will override the text that appears inside a dropzone when it is still empty + +### Expression + +This property will be passed as a string value containing the expression as typed by the user. + +### Text Template + +A preview string will be passed. This preview is built using the currently active language, and by +replacing the placeholders with the names of the attributes. + +For example, you could see these placeholders: + +```text +Name: {1} +Description: {2} +``` + +Using parameters `EventName` and `EventDescription` instead of the placeholders would look like this: + +```text +Name: {EventName} +Description: {EventDescription} +``` + +### Action + +When an action is set, an empty object `{}` is passed to indicate that an action has been set. When no client action is set, the passed value will be `null`. + +### Attribute + +A string containing the path of the selected attribute will be passed. + +Here are a few examples: + +* `EventName` +* `MyFirstModule.EventSchedule_Event/MyFirstModule.Event/EventName` + +### Object + +Object properties are passed as an `array` of JavaScript objects. For each configured sub-object, an object will be passed with all the sub-object's properties. These properties are available by their `key`, with values as described throughout the [Values API](#values) section. + +### File + +A string containing the path of the selected file entity will be passed. + +Here are a few examples: + +* `MyFirstModule.Event` +* `MyFirstModule.EventSchedule_Event/MyFirstModule.Event` + +## Preview Module for the Design Mode + +It is possible to create a preview for pluggable widgets that will be rendered in Studio Pro's Design Mode. + +Add the module by adding a file to your custom widget with the same name as your `xml` file as well as the suffix +`.editorPreview.js`. For example, a widget named `TextBox.xml` would have the preview module `TextBox.editorPreview.js`. + +This preview module is expected to be a CommonJS module, exporting the following functions using the `exports` object. + +### Exposed Libraries + +In **Design mode**, only a few libraries are allowed to be imported. This is expected to occur through the +CommonJS method: by using `require`. + +It is possible to require the following modules: + +* The react libraries `"react"`, `"react-dom"`, `"react-dom-factories"`, and `"prop-types"` +* An `Icon` component that can be used to render icon properties: `"mendix/components/web/Icon"` +* A `Selectable` component that can be used to define what it selectable in preview: `"mendix/preview/Selectable"` + +### Preview Export + +The `preview` export is expected to be a `class` or `function` representing a `React` component. This component, the values object (see the [Values API](#values) section above), and the following properties will be rendered along with the values as properties: + +* `readOnly` (`boolean`): `true` if the widget is read-only (for example, if it is configured to be so due to the `Editability` system property, or if it is inside a read-only data view) +* `renderMode` (`string`): a string providing information on which mode the rendering editor is in + * `design`: the current editor is in design mode + * `xray`: the current editor is in x-ray mode +* `class` (`string`): the classes from the system, which will include manually configured classes through the `class` property in Studio Pro, and the classes resulting from configured design properties +* `style` (`string`): a string representation of the styles as entered in the `style` property in Studio Pro + +Assuming a pluggable widget with the string properties `content` and `style`, the following shows a simple preview component: + +```tsx +type Props = { + content: string; + style: string; + class: string; +} + +export const preview: React.FC = (props) => ( +
+ {props.content} +
+); +``` + +#### Using a Widgets Property + +A [Widgets Property](#widgets) contains a `renderer` field that allows its content to be rendered when filled, or shows an empty drop-zone when empty inside the preview. It requires a single, empty, DOM node as a child in which to render the contents: + +```tsx +type Props = { + content: WidgetsProperty; +} + +export const preview: React.FC = (props) => { + const ContentRenderer = props.content.renderer; + + return ( +
+
+
+
+ ); +} +``` + +#### Using an Icon Property + +The preview module provides a component to preview an [icon property](#icon) in the same way as the +`Icon` component in the client would. This component can be imported from `"mendix/components/web/Icon"` and accepts +the `IconProperty` as `icon` parameter. + +```tsx +import { Icon } from "mendix/components/web/Icon"; + +type Props = { + icon: IconProperty; +} + +export const preview: React.FC = (props) => ( +
+ +
+
+); +``` + +#### Using the Selectable Component + +The preview module provides a component to define that an object is selectable in the preview. This component can be imported from `"mendix/preview/Selectable"`, accepts an item from an `object` list property as an `object` parameter, and has an optional `caption` parameter. + +The example below defines a simplified representation of the types for your clarity. In reality you would import those types from `"../typings/TruckWidgetProps"` if `TruckWidget` was the name of your widget. + +```tsx +import { Selectable } from "mendix/preview/Selectable"; + +type TruckDriversType = { + name: string; + age: number; + isExperienced: boolean; +} + +type TruckWidgetPreviewProps = { + truckDrivers: TruckDriversType[]; +} + +export const preview: React.FC = (props) => ( +
+ {props.truckDrivers.map((truckDriver, i) => ( + +
+
Name: {truckDriver.name}
+
Age: {truckDriver.age}
+
+
+ ))} +
+) +``` + +When the widget is added to a page you can select a specific item and edit it: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/pluggable-widgets-studio-apis/selectable-component.png" alt="Example of the selectable component" class="no-border" >}} + +### The GetPreviewCss Export + +The `getPreviewCss` export is expected to be a `function` returning a `string` containing any CSS that the preview needs +to render. + +```typescript +export function getPreviewCss() { + return ` +.my-pw-container { + background-color: #C0FFEE; +} +`; +} +``` + +## Read More + +* [Configuration Module API for Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-config-api/) +* [Client APIs Available to Pluggable Widgets](/apidocs-mxsdk/apidocs/pluggable-widgets-client-apis/) +* [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/) +* [How to Build a Pluggable Native Widget](/howto/extensibility/build-native-widget/) diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/_index.md new file mode 100644 index 00000000000..d6d746f005c --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/_index.md @@ -0,0 +1,313 @@ +--- +title: "Pluggable Widgets API" +url: /apidocs-mxsdk/apidocs/pluggable-widgets/ +description: "This API helps you to understand pluggable widgets, how they extend app functionality, and how they can be built to interact with Mendix's APIs in Mx11." +no_list: false +description_list: true +weight: 90 +--- + +## Introduction + +Mendix comes with a wide variety of [Widgets](/refguide/pages/#widgets-categories), but sometimes your app requires a widget outside of this set. To support a more advanced UI pattern or create app-specific interactions, you will need to make your own pluggable widget. This documentation will help you achieve that in Studio Pro 11. See these links for other versions' documentation: + +* [Mendix 10](/apidocs-mxsdk/apidocs/pluggable-widgets-10/) +* [Mendix 9](/apidocs-mxsdk/apidocs/pluggable-parent-9/) +* [Mendix 8](/apidocs-mxsdk/apidocs/pluggable-parent-8/) + +Your new pluggable widget can be used while modeling pages alongside standard Mendix components. It can also be shared between multiple apps and distributed through the [Marketplace](/appstore/). + +You are in control of a pluggable widget's appearance and behavior. Customize a pluggable widget by implementing a widget as a plain [React](https://reactjs.org/) component written in JavaScript or TypeScript. The component will be rendered in a Mendix app, and will be able to use APIs provided by Mendix to interact with that app. + +Pluggable widgets, like core widgets, can have properties which a Mendix developer can (and sometimes must) configure every time the widget is used in Mendix Studio Pro. You can define these properties by making a widget definition XML file (for more information on widget definition XML files, see the [Widget Definition XML File](#widget-definition) section below). + +Pluggable widgets can also include a preview component for when they are previewed in Studio Pro's **Design mode**. + +For information on which libraries Mendix supports when developing pluggable widgets, see the [Pluggable Widgets](/refguide/mendix-client/#pluggable-widgets) section of *Mendix Client*. + +For information on how to update Pluggable Widgets Tools to a newer version, see [Updating Pluggable Widgets Tools](/howto/extensibility/update-pluggable-widgets-tools/) + +{{% alert color="info" %}} +Using [System Texts](/refguide/system-texts/) to translate languages is not available for use with the Pluggable Widgets API. +{{% /alert %}} + +## Client Component {#client-component} + +The essential part of a pluggable widget is its client component: a React component rendered inside the end-user’s app. Creating this component requires some basic React knowledge. Read [React's tutorial](https://reactjs.org/tutorial/tutorial.html) if you have not worked with React before. Note that if you are building a widget for [native mobile](/refguide/mobile/) apps, you should use [React Native](https://facebook.github.io/react-native/) instead of React. + +The client component is mainly focused on presentation and interaction with an end-user, while data fetching, validation, and updating are handled by the Mendix Platform. Mendix provides your component with APIs which follow a [unidirectional data flow pattern](https://www.geeksforgeeks.org/unidirectional-data-flow/), much like the [Redux](https://redux.js.org/basics/data-flow) and [Flux](https://facebook.github.io/flux/docs/in-depth-overview#structure-and-data-flow) APIs. Mendix follows the “batteries included but removable” motto. You do not have to care about nuances if standard behavior suffices for you, but you can adjust behaviors when required. + +A widget component is [mounted](https://en.reactjs.org/docs/react-component.html#mounting) and [unmounted](https://en.reactjs.org/docs/react-component.html#unmounting) when a widget is shown or hidden — for example when a page is opened or due to [conditional visibility](/refguide/common-widget-properties/#visibility-properties). A component receives [props](https://en.reactjs.org/docs/components-and-props.html) which resemble properties described in its widget definition XML file. A prop's key comes from the [`key`](#key-attribute) attribute, and its value is based on the configuration of the property. Prop values are immutable, but the Mendix Platform re-renders the component passing new values when necessary. + +A prop value is often not just a primitive value, but an object whose structure depends on the [`type`](#type-attribute) of its widget's property. A prop's values can expose data, metadata, and associated actions — whatever is applicable for the property. Here is an example of one interface. It is a value for an action property, such as the type you would find in the [On click](/refguide/on-click-event/#on-click) property of an action button: + +```ts + export interface ActionValue { + readonly canExecute: boolean; + readonly isExecuting: boolean; + execute(): void; + } +``` + +The above interface could be used this way: a component uses a `canExecute` flag to decide whether it should be enabled, uses an `isExecuting` flag to show an inline progress indicator, and triggers `execute()` method in a reaction to user click. Normally, after `execute()` has been triggered, the component will be re-rendered with a new value that has the `isExecuting` flag set, and when an action, for example a microflow, completes, the component is re-rendered again without `isExecuting`. + +## Widget Package {#widget-package} + +A pluggable widget is distributed as single widget package file with an *.mpk* extension. This file should be placed in your app's `widgets` directory. Mendix Studio Pro discovers all widgets in your app when you open your app, add a widget through the Marketplace, or click **App** > **Synchronize App Directory**. + +Manually building a widget package can be difficult, so Mendix recommends you use scripts provided by the [Mendix Pluggable Widget Generator](https://www.npmjs.com/package/@mendix/generator-widget). For more information on how to use a generator, see [How To Build a Text Box Pluggable Widget: Part 1](/howto/extensibility/create-a-pluggable-widget-one/). + +A widget package file is just a ZIP archive containing the following things: + +* A *package.xml* file describing the whole package +* A widget definition XML file, preferably located in *{widgetName}.xml* where `widgetName` is the last part of widget [ID](#widget-id) +* A client component of a widget located, for example, in *com/mendix/widget/MyProgressCircle.js* for a widget with the ID `com.mendix.widget.MyProgressCircle` +* Optionally, a widget preview Studio Pro’s **Design mode** located in *{widgetName}.editorPreview.js* +* Optionally, widget icons (which must be the PNG format): + * *{widgetName}.icon.png* sets the widget icon inside the Studio Pro toolbox in list view (the ideal image size is 64x64 pixels, but other sizes will be resized to fit) + * *{widgetName}.icon.dark.png* sets the dark-mode equivalent to *{widgetName}.icon.png* + * *{widgetName}.tile.png* sets the tile image inside the Studio Pro toolbox in tile view (the ideal image size is 256x192 pixels, but other sizes will be resized to fit) + * *{widgetName}.tile.dark.png* sets the dark-mode equivalent to *{widgetName}.tile.png* +* Optionally, some widget-related resources, preferably located next to the file which contains the client component + * Note that all CSS files you add (except the one located in the **lib** sub-directory) will automatically be loaded in an app via the widget + +Naming your widget package file after the `widgetName` is best practice. Also, a widget package can include multiple widgets by putting several of the above items in the same widget package. However, creating such packages is *not recommended*. + +The *package.xml* file has the following structure: + +```xml + + + + + + + + +``` + +Both `packageName` and `packageVersion` should be aligned with the app's information in the Marketplace if you wish to publish the package. It is best practice to use the widget ID as a `packageName`. + +## Widget Definition XML File {#widget-definition} + +The widget definition XML file is an essential part of a widget because it describes that widget's basic information and capabilities, such as if that widget can function offline. This file also contains a defined list of properties configurable in the widget. If you use the Mendix Pluggable Widget Generator, the contents of this file will be scaffolded for you. + +A simple widget XML file might look like this: + +```xml + + + {User friendly widget name} + {User friendly short description} + + [properties] + + +``` + +A widget XML file consists of three sections: widget attributes, widget description, and widget properties definition. + +### Widget Attributes + +Here is an example of a widget’s attributes section: + +```xml + +``` + +This section is generated based on options chosen while running the Mendix Pluggable Widget Generator. You will rarely need to modify it after it is generated. This sample widget features several widget attributes: + +* `id` — This the fully qualified name of the widget called widget ID. Using widget ID, the Mendix Platform distinguishes widgets from each other. Widget ID should never be changed after a widget is used in an app or is published in the Marketplace. Reverse domain-style names, as in example above, are recommended. +* `pluginWidget` — This should always be set to `true`. This way, the Mendix Platform can distinguish between the newer pluggable widgets and the older custom widgets. +* `offlineCapable` — This shows if a widget can work while an app is offline. For more information on offline apps, see the [Offline-First](/refguide/offline-first/) guide. A widget that fetches information from a third-party API, for example a widget that fetches airline ticket prices, could not function without an internet connection. If a widget cannot work offline, Mendix Studio Pro will forbid its use on pages that must be available offline. +* `supportedPlatform` — This shows the platforms a widget is compatible with. `Web` describes widgets that are only compatible with web and hybrid mobile apps. `Native` describes widgets that are compatible with native mobile apps. + +### Widget Description {#widget-description} + +The presentation of the widget in Studio Pro is determined by the first set of elements inside the widget tag. The order of these descriptive tags is important, and is demonstrated in the list below. Only the name and description tags are mandatory — the others are optional. The description can be omitted with a self-closing tag: ``: + +* `name` — The display name of the widget. +* `description` — A short written description of the widget. +* `studioProCategory` — See [Toolbox Category](#toolbox-category). +* `helpUrl` — See [Help Page](#help). +* `icon` — See [Icon](#icon). + +```xml + My Progress Card + Displays my progress. +``` + +In Mendix Studio Pro, the widget described above would look like this: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/basic-widget.png" alt="basic widget" >}} + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/basic-widget-progress-card.png" alt="basic progress card in structure mode" >}} + +#### Toolbox Category {#toolbox-category} + +To provide more clarity for Studio Pro users you can specify a toolbox category for your widgets. When provided, it determines a toolbox category for a widget in Studio Pro. It is possible to specify existing built-in categories such as **Data** or **Input** as well as new arbitrary categories like **Maps**. + +When an existing category is specified, then your widget is placed in it next to existing built-in widgets. When a new category is specified, then your widget placed in that new category. + +A category can be provided through the `studioProCategory` tag: + +```xml + Open Street Maps +``` + +In the example above, a widget would be placed under **Open Street Maps widgets** in Studio Pro. Note that **widgets** is added automatically in the Studio Pro UI. + +{{% alert color="info" %}} +When your widget is published in Marketplace and is assigned a special toolbox category by the Marketplace team, that special toolbox category always takes precedence over a developer-configured category. +{{% /alert %}} + +#### Help Page {#help} + +You can provide additional help information to widget users by using a help page. If you do so, a widgets configuration screen will get a **Help** button, assigned to the F1 shortcut key, that opens a specified page. This button is positioned in the lower-left corner of the popup dialog: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/widget-dialog-help-button.png" alt="basic widget" class="no-border" >}} + +A URL of a help page can be provided through the `helpUrl` property after the `description` tag: + +```xml + https://marketplace.mendix.com/link/component/105695/ +``` + +For more complex help pages you can link to a markdown page. For security reasons, URLs have the following restrictions: + +* Must use HTTPS protocol +* Host name must end with *.mendix.com* or *github.com* +* If host name is *github.com* the full URL must end with *.md* + +#### Icon {#icon} + +The `` element accepts a base64 encoded image that is displayed as the widget icon in Studio Pro. The element is optional and can be omitted. When no icon is provided, Studio Pro will display a fallback icon. + +```xml +PHN2Zy...9zdmc+ +``` + +{{% alert color="info" %}} +Bundling the icon in the [widget package](#widget-package) is our recommended approach. The files are easier to work with and allow for more customization. +{{% /alert %}} + +### Widget Properties Definition {#properties-definition} + +This section is represented by the `properties` tag in the widget XML file. It describes widget properties used in Studio Pro to configure the widget. Here is an example of a properties definition section for a widget which shows a progress card for a dashboard: + +```xml + + + + + Label + Card label + + + Icon + Card icon + + + Percentage + Progress percentage + + + + + + + + + Show button + Show button on the card + + + On click + Action to be performed when button is clicked + + + + + + + + Animate + Show progress bar animation + + + Color + Progress bar CSS color + + + + + +``` + +## Property Groups {#property-groups} + +Before examining properties themselves, it is useful to understand property groups. Property groups are formed by properties wrapped in a `propertyGroup` tag. Studio Pro uses the property groups to render how the widget configuration UI appears in Studio Pro. Grouping can be used to help the modeling developer understand the configuration of a more complex widget. It is best practice to both use property groups and group properties based on their purposes. The property groups from the code in [Widget Properties Definition](#properties-definition) above forms the following structure: + +``` + ├── General + │ ├── Main + │ │ ├── Label + │ │ ├── Icon + │ │ └── Percentage + │ │ + │ └── Action + │ ├── Show button + │ ├── On click + │ └── Tab index + │ + └── Visual + └── Progress bar + ├── Animate + └── Color +``` + +This is how the property group structure is represented in Studio Pro: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/edit-progress-card.png" alt="edit progress general" class="no-border" >}} + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/edit-visual-tab.png" alt="edit progress visual" class="no-border" >}} + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/properties-widget.png" alt="properties widget" class="no-border" >}} + +When properties are shown in a dialog box, first-level groups (**General** and **Visual**) are represented as tabs. Second-level groups (**Main**, **Action** and **Progress bar**) are represented as boxes. When properties are shown in a pane, first-level groups are ignored and second-level groups are shown as categories. + +Note that the **Common** and **Appearance** tabs are added to your widget configuration automatically. These tabs contain properties applicable to all widgets: [Name](/refguide/common-widget-properties/#name), [Class](/refguide/common-widget-properties/#class), [Style](/refguide/common-widget-properties/#style), and [Design Properties](/apidocs-mxsdk/apidocs/design-properties/). + +## Widget Property + +This section will explain the shape of the widget property. For more detailed information on widget properties, see [Pluggable Widget Property Types](/apidocs-mxsdk/apidocs/pluggable-widgets-property-types/). Every `property` tag in the Widget Properties Definition has a shape similar to this: + +```xml + + Card name + Name of the card + +``` + +Some properties can or must have more attributes or tags. This depends on the `type` property. The following elements should be present for every property: + +* `key` — This element is a property's unique, single-word identifier. The `key` elements are used internally to identify properties, so they should never change after a widget is used in an app or is published in the Marketplace. A `key` element also identifies a property value when it is passed to a pluggable widget’s client component. +* `type` — This element is a property's type. The `type` element defines which values can be configured for a property, which UI is used in the Mendix Studio Pro, and what type of value a pluggable widget’s client component receives. +* `caption` — This element is a short label identifying a property to a modeling developer. The first letter of a caption should be capitalized. +* `description` — This element is a longer description of a property. A description should be capitalized and limited to one or two sentences. + +Here is how a caption and description look in Studio Pro: + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/card-icon.png" alt="caption" class="no-border" >}} + +{{< figure src="/attachments/apidocs-mxsdk/apidocs/pluggable-widgets/card-description.png" alt="description" class="no-border" >}} + +## Documents in this Section + +Mendix offers the following APIs for pluggable widgets: diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-client-apis/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-client-apis/_index.md similarity index 100% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-client-apis/_index.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-client-apis/_index.md diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md similarity index 100% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-client-apis/pluggable-widgets-client-apis-list-values.md diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-config-api.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-config-api.md similarity index 97% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-config-api.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-config-api.md index 2beeff60aaf..9da4ec3b503 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-config-api.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-config-api.md @@ -1,7 +1,7 @@ --- title: "Configuration Module API" url: /apidocs-mxsdk/apidocs/pluggable-widgets-config-api/ -description: A guide for understanding the configuration module API which influences the behavior of pluggable widgets in Mx10. +description: A guide for understanding the configuration module API which influences the behavior of pluggable widgets in Mx11. weight: 35 aliases: - /apidocs-mxsdk/apidocs/config-api-for-pluggable-widgets diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-native-dependencies.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-native-dependencies.md similarity index 98% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-native-dependencies.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-native-dependencies.md index 24db671ee9f..e5f918bc0e5 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-native-dependencies.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-native-dependencies.md @@ -1,7 +1,7 @@ --- title: "Declaring Native Dependencies" url: /apidocs-mxsdk/apidocs/pluggable-widgets-native-dependencies/ -description: A guide for understanding native dependencies for pluggable widgets and JavaScript actions in Mx10. +description: A guide for understanding native dependencies for pluggable widgets and JavaScript actions in Mx11. weight: 40 aliases: - /apidocs-mxsdk/apidocs/native-dependencies diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-property-types.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-property-types.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-property-types.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-property-types.md index ca2f2216ae1..5e5fd33b6e8 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-property-types.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-property-types.md @@ -1,7 +1,7 @@ --- title: "Property Types" url: /apidocs-mxsdk/apidocs/pluggable-widgets-property-types/ -description: A guide for understanding pluggable widgets' property types in Mx10. +description: A guide for understanding pluggable widgets' property types in Mx11. weight: 10 aliases: - /apidocs-mxsdk/apidocs/property-types-pluggable-widgets diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-studio-apis.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-studio-apis.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-studio-apis.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-studio-apis.md index 5cd80fff9b9..b8c75684d53 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-widgets-studio-apis.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-11/pluggable-widgets/pluggable-widgets-studio-apis.md @@ -2,7 +2,7 @@ title: "Preview Appearance APIs" linktitle: "Preview Appearance APIs" url: /apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis/ -description: A guide for understanding the APIs which influence pluggable widget preview appearances in Mx10. +description: A guide for understanding the APIs which influence pluggable widget preview appearances in Mx11. weight: 30 aliases: - /apidocs-mxsdk/apidocs/studio-apis-for-pluggable-widgets diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/_index.md new file mode 100644 index 00000000000..fac3af20003 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/_index.md @@ -0,0 +1,11 @@ +--- +title: "APIs for Studio Pro 8" +url: /apidocs-mxsdk/apidocs/apis-for-studio-pro-8/ +no_list: false +description_list: true +description: "Provides the documentation of APIs for Studio Pro 8, such as Mendix Runtime API." +weight: 8 +linktitle: "Studio Pro 8" +--- + +Mendix offers the following APIs for Studio Pro 8: diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/_index.md new file mode 100644 index 00000000000..faf4a3c07f1 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/_index.md @@ -0,0 +1,11 @@ +--- +title: "Pluggable Widgets API" +no_list: false +description_list: true +url: /apidocs-mxsdk/apidocs/pluggable-parent-8/ +weight: 90 +description: "This API helps you to understand pluggable widgets, how they extend app functionality, and how they can be built to interact with Mendix's APIs in Mx8." +--- + +The following Mendix 8 pluggable widget API documents are available here: + diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/client-apis-for-pluggable-widgets-8.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/client-apis-for-pluggable-widgets-8.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/client-apis-for-pluggable-widgets-8.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/client-apis-for-pluggable-widgets-8.md index 29d7f168d6f..3bb4611e697 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/client-apis-for-pluggable-widgets-8.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/client-apis-for-pluggable-widgets-8.md @@ -1,5 +1,5 @@ --- -title: "Client APIs – Mx8" +title: "Client APIs" linktitle: "Client APIs for Pluggable Widgets" url: /apidocs-mxsdk/apidocs/client-apis-for-pluggable-widgets-8/ weight: 20 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/differences-between-pluggable-and-custom-widgets.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/differences-between-pluggable-and-custom-widgets.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/differences-between-pluggable-and-custom-widgets.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/differences-between-pluggable-and-custom-widgets.md index 1baa5dc4dae..42e4a3fedc8 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/differences-between-pluggable-and-custom-widgets.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/differences-between-pluggable-and-custom-widgets.md @@ -1,5 +1,5 @@ --- -title: "Compare Pluggable and Custom Widgets – Mx8" +title: "Compare Pluggable and Custom Widgets" linktitle: "Compare Pluggable and Custom Widgets" url: /apidocs-mxsdk/apidocs/differences-between-pluggable-and-custom-widgets/ description: This document explains the differences between pluggable and custom widgets. diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/property-types-pluggable-widgets-8.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/property-types-pluggable-widgets-8.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/property-types-pluggable-widgets-8.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/property-types-pluggable-widgets-8.md index 9c7d3c454fe..1a244188f15 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/property-types-pluggable-widgets-8.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/property-types-pluggable-widgets-8.md @@ -1,5 +1,5 @@ --- -title: "Property Types – Mx8" +title: "Property Types" url: /apidocs-mxsdk/apidocs/property-types-pluggable-widgets-8/ weight: 10 description: A guide for understanding pluggable widgets' property types. diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/studio-apis-for-pluggable-widgets-8.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/studio-apis-for-pluggable-widgets-8.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/studio-apis-for-pluggable-widgets-8.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/studio-apis-for-pluggable-widgets-8.md index d3f7a501080..785a8d2e919 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-8/studio-apis-for-pluggable-widgets-8.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-8/pluggable-widgets/studio-apis-for-pluggable-widgets-8.md @@ -1,5 +1,5 @@ --- -title: "Preview Appearance APIs – Mx8" +title: "Preview Appearance APIs" linktitle: "Preview Appearance APIs" url: /apidocs-mxsdk/apidocs/studio-apis-for-pluggable-widgets-8/ weight: 30 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/_index.md new file mode 100644 index 00000000000..12302d58229 --- /dev/null +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/_index.md @@ -0,0 +1,11 @@ +--- +title: "Pluggable Widgets API" +no_list: false +description_list: true +url: /apidocs-mxsdk/apidocs/pluggable-parent-9/ +weight: 90 +description: "This API helps you to understand pluggable widgets, how they extend app functionality, and how they can be built to interact with Mendix's APIs in Mx9." +--- + +The following Mendix 9 pluggable widget API documents are available here: + diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-client-apis-9/_index.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-client-apis-9/_index.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-client-apis-9/_index.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-client-apis-9/_index.md index 1bba77000be..cb5e20b8e4f 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-client-apis-9/_index.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-client-apis-9/_index.md @@ -1,5 +1,5 @@ --- -title: "Client APIs – Mx9" +title: "Client APIs" linktitle: "Client APIs for Pluggable Widgets" url: /apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-9/ description: A guide for understanding the client APIs available to pluggable widgets in Mendix 9. diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-client-apis-9/pluggable-widgets-client-apis-list-values-9.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-client-apis-9/pluggable-widgets-client-apis-list-values-9.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-client-apis-9/pluggable-widgets-client-apis-list-values-9.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-client-apis-9/pluggable-widgets-client-apis-list-values-9.md index 02ae3c02978..87c79d2b625 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-client-apis-9/pluggable-widgets-client-apis-list-values-9.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-client-apis-9/pluggable-widgets-client-apis-list-values-9.md @@ -1,5 +1,5 @@ --- -title: "List Values – Mx9" +title: "List Values" url: /apidocs-mxsdk/apidocs/pluggable-widgets-client-apis-list-values-9/ description: A guide to understanding the list of objects for the datasource property. --- diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-config-api-9.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-config-api-9.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-config-api-9.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-config-api-9.md index 577ce7caf49..081cff891da 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-config-api-9.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-config-api-9.md @@ -1,5 +1,5 @@ --- -title: "Configuration Module API – Mx9" +title: "Configuration Module API" url: /apidocs-mxsdk/apidocs/pluggable-widgets-config-api-9/ description: A guide for understanding the configuration module API which influences the behavior of pluggable widgets in Studio Pro Mendix 9. weight: 35 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-native-dependencies-9.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-native-dependencies-9.md similarity index 98% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-native-dependencies-9.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-native-dependencies-9.md index 61115c2b4ae..9a52ff304d7 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-native-dependencies-9.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-native-dependencies-9.md @@ -1,5 +1,5 @@ --- -title: "Declaring Native Dependencies – Mx9" +title: "Declaring Native Dependencies" url: /apidocs-mxsdk/apidocs/pluggable-widgets-native-dependencies-9/ description: A guide for understanding native dependencies for pluggable widgets and JavaScript actions in Mendix 9. weight: 40 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-property-types-9.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-property-types-9.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-property-types-9.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-property-types-9.md index 44d837d5d18..88a94182241 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-property-types-9.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-property-types-9.md @@ -1,5 +1,5 @@ --- -title: "Property Types – Mx9" +title: "Property Types" url: /apidocs-mxsdk/apidocs/pluggable-widgets-property-types-9/ description: A guide for understanding pluggable widgets' property types in Studio Pro Mendix 9. weight: 10 diff --git a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-studio-apis-9.md b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-studio-apis-9.md similarity index 99% rename from content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-studio-apis-9.md rename to content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-studio-apis-9.md index b429e4c2292..ba06c976a3d 100644 --- a/content/en/docs/apidocs-mxsdk/apidocs/frontend/pluggable-widgets/pluggable-parent-9/pluggable-widgets-studio-apis-9.md +++ b/content/en/docs/apidocs-mxsdk/apidocs/studio-pro-9/pluggable-widgets/pluggable-widgets-studio-apis-9.md @@ -1,5 +1,5 @@ --- -title: "Preview Appearance APIs – Mx9" +title: "Preview Appearance APIs" linktitle: "Preview Appearance APIs" url: /apidocs-mxsdk/apidocs/pluggable-widgets-studio-apis-9/ description: A guide for understanding the APIs which influence pluggable widget preview appearances.