Widget and validation gallery
This gallery shows how widgets and validations are rendered in both Studio and web environments, along with sample implementation code.
You can also find sample working components for each of the configuration cases below:
-
ActiveIf: Add visibility conditions on some configurations.
-
Checkbox: Add checkboxes or toggles to your component.
-
Code: Allow users to enter their own code.
-
Credential: Mark a configuration as sensitive data to avoid displaying it as plain text.
-
Datastore: Add a button allowing to check the connection to a datastore.
-
Datalist: Two ways of implementing a dropdown list with predefined choices.
-
Integer: Add numeric fields to your component configuration.
-
Min/Max: Specify a minimum or a maximum value for a numeric configuration.
-
Multiselect: Add a list and allow users to select multiple elements of that list.
-
Pattern: Enforce rules based on a specific a pattern to prevent users from entering invalid values.
-
Required: Make a configuration mandatory.
-
Suggestions: Suggest possible values in a field based on what the users are entering.
-
Table: Add a table to your component configuration.
-
Textarea: Add a text area for configurations expecting long texts or values.
-
Input: Add a simple text input field to the component configuration
-
Update: Provide a button allowing to fill a part of the component configuration based on a service.
-
Validation: Specify constraints to make sure that a URL is well formed.
Widgets
Widgets allow to easily implement different types of input fields to your components.
Integer
@Option
@Documentation("This is a number")
public Integer number;
Studio Rendering | Web Rendering |
---|---|
Datetime
Datetime fields rely on the Java Date Time API, including LocalTime
, LocalDate
, LocalDateTime
and ZonedDateTime
classes.
@Option
LocalDateTime startTime;
=== |Studio Rendering | Web Rendering
|image::gallery/widgets/studio/widget_calendar.png[Studio Calendar,40%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/widget_calendar.png"] |image::gallery/widgets/web/widget_calendar.png[Web Calendar,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/widget_calendar.png"]
=== List [source,java] ---- @Option @Proposable("valuesProvider") String config; / service class */ @DynamicValues("valuesProvider") public Values actions(){ return new Values(asList(new Values.Item("1", "Delete"), new Values.Item("2", "Insert"), new Values.Item("3", "Update"))); } ---- or [source,java] ---- @Option ActionEnum config; / Define enum */ enum ActionEnum { Delete, Insert, Update } ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/list.png[Studio List,40%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/list.png"] |image::gallery/widgets/web/list.png[Web List,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/list.png"]
=== Suggestions [source,java] ---- @Option @Suggestable(value = "loadModules", parameters = { "myconfig" }) @Documentation("module names are loaded using service") public String moduleName; @Suggestions("loadModules") public SuggestionValues loadModules(@Option final MyConfig myconfig) { } ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/studio_talend_component_kit_suggestion_widget_loading.png[Studio suggestions loading,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/studio_talend_component_kit_suggestion_widget_loading.png"] |image::gallery/widgets/web/web_talend_component_kit_suggestion_widget_loading.png[Web suggestions loading,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/web_talend_component_kit_suggestion_widget_loading.png"] |image::gallery/widgets/studio/studio_talend_component_kit_suggestion_widget_loaded.png[Studio suggestions loaded,80%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/studio_talend_component_kit_suggestion_widget_loaded.png"] |image::gallery/widgets/web/web_talend_component_kit_suggestion_widget_loaded.png[Web suggestions loaded,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/web_talend_component_kit_suggestion_widget_loaded.png"]
=== Table [source,java] ---- @Option List<MyObject> config; ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/table.png[Studio Table,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/table.png"] |image::gallery/widgets/web/table.png[Web Table,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/table.png"]
=== Code [source,java] ---- @Code("java") @Option String config; ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/javaCode.png[Studio Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/javaCode.png"] |image::gallery/widgets/web/javaCode.png[Web Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/javaCode.png"]
=== Schema [source,java] ---- @Option @Structure List<String> config; ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/schema.png[Studio Schema,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/schema.png"] |image::gallery/widgets/web/schema.png[Web Schema,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/schema.png"]
== Validations Validations help restricting what can be entered or selected in an input field, to make sure that the value complies with the expected type of information. === Property validation [source,java] ---- / configuration class */ @Option @Validable("url") String config; / service class */ @AsyncValidation("url") ValidationResult doValidate(String url) { } ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/validation_property.png[Studio Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/validation_property.png"] |image::gallery/widgets/web/validation_property.png[Web Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/validation_property.png"]
=== Property validation with Pattern [source,java] ---- /** configuration class */ @Option @Pattern("/^[a-zA-Z\\-]+$/") String username; ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/validation_pattern.png[Studio Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/validation_pattern.png"] |image::gallery/widgets/web/validation_pattern.png[Web Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/validation_pattern.png"]
=== Data store validation [source,java] ---- @Datastore @Checkable public class config { / config …*/ } / service class */ @HealthCheck public HealthCheckStatus testConnection(){ } ---- [cols="1a,1a",role="table gallery table-striped",options="header,autowidth",width="100%"] |
|Studio Rendering | Web Rendering
|image::gallery/widgets/studio/validation_datastore.png[Studio Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/studio/prop_validation.png"] |image::gallery/widgets/web/validation_datastore.png[Web Code,100%,window="_blank",link="https://talend.github.io/component-runtime/main/1.1.10/_images/gallery/widgets/web/prop_validation.png"]
You can also use other types of validation that are similar to * :leveloffset!: == Actions :leveloffset: +2 = Dynamic Values Mark a method as being useful to fill potential values of a string option for a property denoted by its value. You can link a field as being completable using @Proposable(value). The resolution of the completion action is then done through the component family and value of the action. The callback doesn’t take any parameter. - Type: [source,js] ---- { "items":[ { "id":"value", "label":"label" } ] } ---- = Healthcheck This class marks an action doing a connection test - Type: [source,js] ---- { "comment":"Something went wrong", "status":"KO" } ---- = Schema Mark an action as returning a discovered schema. Its parameter MUST be a dataset. Dataset is configuration type annotated with @DataSet. If component has multiple datasets, then dataset used as action parameter should have the same identifier as this @DiscoverSchema. - Type: [source,js] ---- { "entries":[ { "comment":"The column 1", "name":"column1", "nullable":false, "type":"STRING" }, { "comment":"The int column", "name":"column2", "nullable":false, "type":"INT" } ], "type":"RECORD" } ---- = Suggestions Mark a method as being useful to fill potential values of a string option. You can link a field as being completable using @Suggestable(value). The resolution of the completion action is then done when the user requests it (generally by clicking on a button or entering the field depending the environment). - Type: [source,js] ---- { "cacheable":false, "items":[ { "id":"value", "label":"label" } ] } ---- = Update This class marks an action returning a new instance replacing part of a form/configuration. - Type: = User Extension point for custom UI integrations and custom actions. - Type: = Validation Mark a method as being used to validate a configuration. IMPORTANT: this is a server validation so only use it if you can’t use other client side validation to implement it. - Type: [source,js] ---- { "comment":"Something went wrong", "status":"KO" } ---- == Built In Actions These actions are provided - or not - by the application the UI runs within. TIP: always ensure you don’t require this action in your component. = built_in_suggestable Mark the decorated field as supporting suggestions, i.e. dynamically get a list of valid values the user can use. It is however different from - API: :leveloffset: 1 == Conditions :leveloffset: +2 = ActiveIf If the evaluation of the element at the location matches value then the element is considered active, otherwise it is deactivated. - API: [source,js] ---- { "condition::if::evaluationStrategy":"DEFAULT", "condition::if::negate":"false", "condition::if::target":"test", "condition::if::value":"value1,value2" } ---- = ActiveIfs Allows to set multiple visibility conditions on the same property. - API: [source,js] ---- { "condition::if::evaluationStrategy::0":"DEFAULT", "condition::if::evaluationStrategy::1":"LENGTH", "condition::if::negate::0":"false", "condition::if::negate::1":"true", "condition::if::target::0":"sibling1", "condition::if::target::1":"../../other", "condition::if::value::0":"value1,value2", "condition::if::value::1":"SELECTED", "condition::ifs::operator":"AND" } ---- :leveloffset: 1 == Configuration types :leveloffset: +2 = Dataset Mark a model (complex object) as being a dataset. - API: @org.talend.sdk.component.api.configuration.type.DataSet - Sample: [source,js] ---- { "tcomp::configurationtype::name":"test", "tcomp::configurationtype::type":"dataset" } ---- = Datastore Mark a model (complex object) as being a datastore (connection to a backend). - API: @org.talend.sdk.component.api.configuration.type.DataStore - Sample: [source,js] ---- { "tcomp::configurationtype::name":"test", "tcomp::configurationtype::type":"datastore" } ---- :leveloffset: 1 == Constraints :leveloffset: +2 = MaxLength Ensure the decorated option size is validated with a higher bound. - API: [source,js] ---- { "validation::maxLength":"12.34" } ---- = MinLength Ensure the decorated option size is validated with a lower bound. - API: [source,js] ---- { "validation::minLength":"12.34" } ---- = Pattern Validate the decorated string with a javascript pattern (even into the Studio). - API: [source,js] ---- { "validation::pattern":"test" } ---- = Max Ensure the decorated option size is validated with a higher bound. - API: [source,js] ---- { "validation::max":"12.34" } ---- = Min Ensure the decorated option size is validated with a lower bound. - API: [source,js] ---- { "validation::min":"12.34" } ---- = Required Mark the field as being mandatory. - API: [source,js] ---- { "validation::required":"true" } ---- = MaxItems Ensure the decorated option size is validated with a higher bound. - API: [source,js] ---- { "validation::maxItems":"12.34" } ---- = MinItems Ensure the decorated option size is validated with a lower bound. - API: [source,js] ---- { "validation::minItems":"12.34" } ---- = UniqueItems Ensure the elements of the collection must be distinct (kind of set). - API: [source,js] ---- { "validation::uniqueItems":"true" } ---- :leveloffset: 1 == Junit environments NOTE: the configuration is read from system properties, environment variables, …. Contextual:: class: ContextualEnvironment_. Direct:: class: DirectRunnerEnvironment_. Flink:: class: FlinkRunnerEnvironment_. Spark:: class: SparkRunnerEnvironment_. == Scanning :leveloffset: +2 = Package Scanning Since the framework can be used in the case of fatjars or shades, and because it still uses scanning, it is important to ensure we don’t scan the whole classes for performances reason. Therefore, the following packages are ignored: [.talend-filterlist] - avro.shaded - com.codehale.metrics - com.ctc.wstx - com.datastax.driver.core - com.fasterxml.jackson.annotation - com.fasterxml.jackson.core - com.fasterxml.jackson.databind - com.fasterxml.jackson.dataformat - com.fasterxml.jackson.module - com.google.common - com.google.thirdparty - com.ibm.wsdl - com.jcraft.jsch - com.kenai.jffi - com.kenai.jnr - com.sun.istack - com.sun.xml.bind - com.sun.xml.messaging.saaj - com.sun.xml.txw2 - com.thoughtworks - io.jsonwebtoken - io.netty - io.swagger.annotations - io.swagger.config - io.swagger.converter - io.swagger.core - io.swagger.jackson - io.swagger.jaxrs - io.swagger.model - io.swagger.models - io.swagger.util - javax - jnr - junit - net.sf.ehcache - net.shibboleth.utilities.java.support - org.aeonbits.owner - org.apache.activemq - org.apache.beam - org.apache.bval - org.apache.camel - org.apache.catalina - org.apache.commons.beanutils - org.apache.commons.cli - org.apache.commons.codec - org.apache.commons.collections - org.apache.commons.compress - org.apache.commons.dbcp2 - org.apache.commons.digester - org.apache.commons.io - org.apache.commons.jcs.access - org.apache.commons.jcs.admin - org.apache.commons.jcs.auxiliary - org.apache.commons.jcs.engine - org.apache.commons.jcs.io - org.apache.commons.jcs.utils - org.apache.commons.lang - org.apache.commons.lang3 - org.apache.commons.logging - org.apache.commons.pool2 - org.apache.coyote - org.apache.cxf - org.apache.geronimo.javamail - org.apache.geronimo.mail - org.apache.geronimo.osgi - org.apache.geronimo.specs - org.apache.http - org.apache.jcp - org.apache.johnzon - org.apache.juli - org.apache.logging.log4j.core - org.apache.logging.log4j.jul - org.apache.logging.log4j.util - org.apache.logging.slf4j - org.apache.meecrowave - org.apache.myfaces - org.apache.naming - org.apache.neethi - org.apache.openejb - org.apache.openjpa - org.apache.oro - org.apache.tomcat - org.apache.tomee - org.apache.velocity - org.apache.webbeans - org.apache.ws - org.apache.wss4j - org.apache.xbean - org.apache.xml - org.apache.xml.resolver - org.bouncycastle - org.codehaus.jackson - org.codehaus.stax2 - org.codehaus.swizzle.Grep - org.codehaus.swizzle.Lexer - org.cryptacular - org.eclipse.jdt.core - org.eclipse.jdt.internal - org.fusesource.hawtbuf - org.h2 - org.hamcrest - org.hsqldb - org.jasypt - org.jboss.marshalling - org.joda.time - org.jose4j - org.junit - org.jvnet.mimepull - org.metatype.sxc - org.objectweb.asm - org.objectweb.howl - org.openejb - org.opensaml - org.slf4j - org.swizzle - org.terracotta.context - org.terracotta.entity - org.terracotta.modules.ehcache - org.terracotta.statistics - org.tukaani - org.yaml.snakeyaml - serp NOTE: it is not recommanded but possible to add in your plugin module a
:leveloffset: 1 == Server configuration NOTE: the configuration is read from system properties, environment variables, …. talend.component.server.cache.maxSize:: Default value: - a talend.component.server.user.extensions.provisioning.location:: Default value: == User Interface API :leveloffset: +2 = @DefaultValue Provide a default value the UI can use - only for primitive fields. - API: == Snippets [source,js] ---- { "ui::defaultvalue::value":"test" } ---- = @OptionsOrder Allows to sort a class properties. - API: == Snippets [source,js] ---- { "ui::optionsorder::value":"value1,value2" } ---- = @AutoLayout Request the rendered to do what it thinks is best. - API: == Snippets [source,js] ---- { "ui::autolayout":"true" } ---- = @GridLayout Advanced layout to place properties by row, this is exclusive with - API: == Snippets [source,js] ---- { "ui::gridlayout::value1::value":"first |
second,third", "ui::gridlayout::value2::value":"first |
second,third" } ---- = @GridLayouts Allow to configure multiple grid layouts on the same class, qualified with a classifier (name) - API: == Snippets [source,js] ---- { "ui::gridlayout::Advanced::value":"another", "ui::gridlayout::Main::value":"first |
second,third" } ---- = @HorizontalLayout Put on a configuration class it notifies the UI an horizontal layout is preferred. - API: == Snippets [source,js] ---- { "ui::horizontallayout":"true" } ---- = @VerticalLayout Put on a configuration class it notifies the UI a vertical layout is preferred. - API: == Snippets [source,js] ---- { "ui::verticallayout":"true" } ---- = @Code Mark a field as being represented by some code widget (vs textarea for instance). - API: == Snippets [source,js] ---- { "ui::code::value":"test" } ---- = @Credential Mark a field as being a credential. It is typically used to hide the value in the UI. - API: == Snippets [source,js] ---- { "ui::credential":"true" } ---- = @DateTime Mark a field as being a date. It supports and is implicit - which means you don’t need to put that annotation on the option - for - API: == Snippets [source,js] ---- { "ui::datetime":"time" } ---- [source,js] ---- { "ui::datetime":"date" } ---- [source,js] ---- { "ui::datetime":"datetime" } ---- [source,js] ---- { "ui::datetime":"zoneddatetime" } ---- = @Structure Mark a List<String> or Map<String, String> field as being represented as the component data selector (field names generally or field names as key and type as value). - API: == Snippets [source,js] ---- { "ui::structure::discoverSchema":"test", "ui::structure::type":"IN", "ui::structure::value":"test" } ---- = @TextArea Mark a field as being represented by a textarea(multiline text input). - API: == Snippets [source,js] ---- { "ui::textarea":"true" } ---- :leveloffset: 1 |