If you want to use JavaScript, you can define a custom styleName for textArea
component and use JavaScript#eval()
method:
@Inject
protected Dialogs dialogs;
@Autowired
private UiComponents uiComponents;
@Subscribe("clickBtn")
public void onClickBtnClick(Button.ClickEvent event) {
AtomicInteger cursorPosition = new AtomicInteger();
dialogs.createInputDialog(this)
.withParameter(InputParameter.parameter("textAreaParam")
.withField(() -> {
TextArea<String> textArea = uiComponents.create(TextArea.NAME);
textArea.setWidthFull();
textArea.setStyleName("js-text-area");
return textArea;
}
))
.withActions(InputDialogAction.action("specialAction")
.withCaption("Insert special symbol")
.withShortcut("SHIFT-A")
.withHandler(actionEvent -> JavaScript.eval(String.format(
"var el = document.querySelector('.js-text-area');" +
"var pos = el.selectionStart;" +
"el.value = el.value.substr(0, pos) + '%s' + el.value.substr(pos);",
"$"))))
.show();
}
Or you can create a composite component that includes TextArea
component and JavaScriptComponent
:
JavaScriptTextArea
@CompositeDescriptor("js-text-area.xml")
public class JavaScriptTextArea extends CompositeComponent<HBoxLayout>
implements Field<String>,
CompositeWithCaption,
CompositeWithDescription,
CompositeWithContextHelp,
CompositeWithHtmlCaption,
CompositeWithHtmlDescription,
CompositeWithIcon {
public static final String NAME = "javaScriptTextArea";
protected TextArea<String> textArea;
protected JavaScriptComponent jsComponent;
public JavaScriptTextArea() {
addCreateListener(this::onCreate);
}
protected void onCreate(CreateEvent createEvent) {
textArea = getInnerComponent("textArea");
jsComponent = getInnerComponent("jsComponent");
JavaScript.getCurrent().execute(jsComponent.getInitFunctionName() + "()");
}
@Override
public boolean isRequired() {
return textArea.isRequired();
}
@Override
public void setRequired(boolean required) {
textArea.setRequired(required);
}
@Override
public String getRequiredMessage() {
return textArea.getRequiredMessage();
}
@Override
public void setRequiredMessage(String msg) {
textArea.setRequiredMessage(msg);
}
@Override
public void addValidator(Consumer<? super String> validator) {
textArea.addValidator(validator);
}
@Override
public void removeValidator(Consumer<String> validator) {
textArea.removeValidator(validator);
}
@Override
public Collection<Consumer<String>> getValidators() {
return textArea.getValidators();
}
@Override
public boolean isEditable() {
return textArea.isEditable();
}
@Override
public void setEditable(boolean editable) {
textArea.setEditable(editable);
}
@Nullable
@Override
public String getValue() {
return textArea.getValue();
}
@Override
public void setValue(@Nullable String value) {
textArea.setValue(value);
}
@Override
public Subscription addValueChangeListener(Consumer<ValueChangeEvent<String>> listener) {
return textArea.addValueChangeListener(listener);
}
@Override
public void removeValueChangeListener(Consumer<ValueChangeEvent<String>> listener) {
textArea.removeValueChangeListener(listener);
}
@Override
public boolean isValid() {
return textArea.isValid();
}
@Override
public void validate() throws ValidationException {
textArea.validate();
}
@Override
public void setValueSource(@Nullable ValueSource<String> valueSource) {
textArea.setValueSource(valueSource);
}
@Nullable
@Override
public ValueSource<String> getValueSource() {
return textArea.getValueSource();
}
public void insertCharacter(String character) {
jsComponent.callFunction("insertCharacter", character);
}
}
JavaScriptTextAreaLoader
public class JavaScriptTextAreaLoader extends AbstractFieldLoader<JavaScriptTextArea> {
@Override
public void createComponent() {
resultComponent = factory.create(JavaScriptTextArea.NAME);
loadId(resultComponent, element);
}
}
js-text-area.xml
<composite xmlns="http://schemas.haulmont.com/cuba/screen/composite.xsd">
<hbox expand="textArea">
<textArea id="textArea" stylename="js-text-area"/>
<jsComponent id="jsComponent"
height="100%"
initFunctionName="com_company_sample_JavaScriptTextArea">
<dependencies>
<dependency path="vaadin://java-script-text-area-connector.js"/>
</dependencies>
</jsComponent>
</hbox>
</composite>
ui-component.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<components xmlns="http://schemas.haulmont.com/cuba/components.xsd">
<component>
<name>javaScriptTextArea</name>
<componentLoader>com.company.sample.web.components.jstextarea.JavaScriptTextAreaLoader</componentLoader>
<class>com.company.sample.web.components.jstextarea.JavaScriptTextArea</class>
</component>
</components>
ui-component.xsd
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://schemas.company.com/demo/0.1/ui-component.xsd"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://schemas.company.com/demo/0.1/ui-component.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:layout="http://schemas.haulmont.com/cuba/screen/layout.xsd">
<xs:element name="javaScriptTextArea">
<xs:complexType>
<xs:complexContent>
<xs:extension base="layout:baseFieldComponent">
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
web-app.properties
cuba.web.componentsConfig = +com/company/sample/ui-component.xml
java-scipt-text-area-connector.js
com_company_sample_JavaScriptTextArea = function () {
this.insertCharacter = function (character) {
var textArea = document.querySelector(".js-text-area");
var pos = textArea.selectionStart;
textArea.value = textArea.value.substr(0, pos) + character + textArea.value.substr(pos);
}
};
NewScreen
@Inject
protected Dialogs dialogs;
@Autowired
private UiComponents uiComponents;
@Subscribe("clickBtn")
public void onClickBtnClick(Button.ClickEvent event) {
AtomicInteger cursorPosition = new AtomicInteger();
dialogs.createInputDialog(this)
.withParameter(InputParameter.parameter("textAreaParam")
.withField(() -> {
JavaScriptTextArea textArea = uiComponents.create(JavaScriptTextArea.NAME);
textArea.setWidthFull();
return textArea;
}
))
.withActions(InputDialogAction.action("specialAction")
.withCaption("Insert special symbol")
.withShortcut("SHIFT-A")
.withHandler(actionEvent -> {
Form form = (Form) actionEvent.getInputDialog().getDialogWindow().getComponentNN("form");
JavaScriptTextArea textArea = (JavaScriptTextArea) form.getComponentNN("textAreaParam");
textArea.insertCharacter("$");
}))
.show();
}
Regards,
Gleb