Vaadin 14 Grid in non-buffered mode exit editor - vaadin

I've created a custom field in Vaadin14 that displays a grid and two buttons (add row / clear grid). This custom field is displayed in a CRUD editor, editor that in turn has tabs.
For creating the grid with editor I've used the example shown here https://vaadin.com/docs/v14/ds/components/grid in the "Non-buffered" section.
Everything works as expected except for the addCloseHandler(Component, Editor). In the example shown above the code for the close handler method is this one:
textField.getElement().addEventListener("keydown", e -> editor.cancel()).setFilter("event.code === 'Escape'");
which closes the editor when pressing the Esc key or clicking outside the cell that's in edit mode.
My problem is that, given the grid with the editor are inside a CRUD form when I'm hitting Esc the CRUD discard changes form is being shown instead of the editor closing. Also, when clicking outside the edited cell nothing happens.
I believe this is due to the "event.code" in the setFilter method being incorrect but I'm unsure how to determine what is the proper event code that's being triggered in my case.
I tried changing the event from "keydown" to "focusout" which led to the callback method being called when I clicked outside the cell that was being edited but nonetheless the editor did not close (I.e. the cell was stuck in edit mode). I also tried calling editor.close() inside the callback method but with no success.

From https://vaadin.com/docs/v14/ds/components/grid in the "Non-buffered" section:
In the example below, double-click a row to start editing. Press
Escape, or click on a different row to stop editing.
This kotlin code has exactly the same behavior
var clickRegistration :Registration? = null
fun addCloseHandler(field: Component, editor: Editor<*>) {
field.element.addEventListener("keydown") { event ->
editor.cancel()
clickRegistration?.remove()
}.filter = "event.key === 'Escape'"
}
grid.addItemDoubleClickListener { e: ItemDoubleClickEvent<DataSet?> ->
editor.editItem(e.item)
val editorComponent = e.column.editorComponent
if (editorComponent is Focusable<*>) {
(editorComponent as Focusable<*>).focus()
}
clickRegistration = grid.addItemClickListener { event ->
editor.cancel()
clickRegistration?.remove()
}
}

You must use event.key not event.code:
getElement().addEventListener("keydown", event -> editor.cancel())
.setFilter("event.key === 'Escape' || event.key === 'Esc'");

Related

stop event propagation for Vaadin Flow buttons

I have a Vaadin 23 application where I have a Div element with a Button in it (among other content) and a click listener added to it, as well as to the button:
Button button = new Button();
button.addClickListener(event -> { ... });
Div wrapper = new Div(button);
wrapper.addClickListener(event -> { ... });
The problem is that both listeners are firing when the button is clicked.
How can I make sure that only the button click listener is fired in that case? I want the click listener on the Div to fire when I click anywhere inside the Div except on the button.
Alternatively, if I could detect in the click listener on the Div that the click was actually on the button, I could simply ignore it. But I don't see how to do that either.
This is a port from a Vaadin 8 app where it was working correctly. The wrapper Div in that case was a CssLayout with a LayoutClickListener added.
There is a highly voted issue for adding this feature to Vaadin Flow. Different workarounds are also described in the issue.
In your case, I think the workaround would look like this:
button.getElement().addEventListener("click", ignore -> {}).addEventData("event.stopPropagation()");

How to get left click to work on column visibility example using the Vaadin Flow Grid example

On the Column Visibility example on https://vaadin.com/docs/latest/ds/components/grid/#column-visibility the code shows a class ColumnToggleContextMenu which isn't part of the Vaadin API however it seems to somehow adjust how the button is hooked so that it can be left clicked rather than the default right click for a context menu. With that in mind the code below will only show the context menu on a right click, I cannot get it to work like the example code. My code is:
Button showHideColumnsButton = new Button("Show/Hide Columns");
showHideColumnsButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
ContextMenu contextMenu = new ContextMenu(showHideColumnsButton);
for(Grid.Column column : grid.getColumns()) {
contextMenu.addItem(getColumnName(column), e -> showHideColumn(column));
}
I'm considering using a MenuBar instead to see if that will work but I'd prefer to figure out how to use a Button if possible as that seems more appropriate (mainly because it allows the checkbox to show if a column is visible or hidden).
In order to make the context menu to open on left click use setOpenOnClick(true):
Button showHideColumnsButton = new Button("Show/Hide Columns");
showHideColumnsButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
ContextMenu contextMenu = new ContextMenu(showHideColumnsButton);
contextMenu.setOpenOnClick(true)
for(Grid.Column column : grid.getColumns()) {
contextMenu.addItem(getColumnName(column), e -> showHideColumn(column));
}

Using "Button" from Toolbox in Vector Panel Designer, for a CAPL

I am writing testcases in CAPL and want to activate each test case by using "Button" from Panel Designer.
The problem is that whenever I pressed the Button, it reacted as if it were pressed twice.
I just simply add a code like this to make that problem visible.
(The system variable of "#sysvar::Test_Cases::TC1" is linked to the Button in the Panel Editor)
on sysvar sysvar::Test_Cases::TC1
{
putValueToControl("Window","CAPL Output View",#sysvar::Test_Cases::TC1);
}
I expect to see only --> Value of #sysvar::Test_Cases::TC1 =1
But the output is like this:
Value of #sysvar::Test_Cases::TC1 =1
Value of #sysvar::Test_Cases::TC1 =0
on sysvar X{...} event procedure reacts to value change of X.So in case of button press (0->1) value will be set to one then on button release (1->0) value will be set to zero, so you change the value of X twice. This is why you are getting trigger twice.
To react only once on such button press event, and get notification only once, please use the keyword this and condition statement.
on sysvar sysvar::Test_Cases::TC1
{
if (this==1) /* Following block is called only once, on button press 0->1 */
{
putValueToControl("Window","CAPL Output View",#sysvar::Test_Cases::TC1);
}
}

how to toggle using multiple buttons and pass info to the output JQuery

JQUERY CODE:
$('#selector button').click(function() {
$(this).addClass('active').siblings().removeClass('active');
$('#gaga').toggle
})
PUG CODE FOR #gaga element:
p#gaga
| This is `${Value}`
PUG CODE FOR #gaga element:
How can I use three buttons to toggle the #gaga element on when button is active and off when you click outside the specific button and pass a different Value for ${Value} depending on the clicked button. Plus have only one instance of #gaga element running at a time. Meaning if I click the first button then click the second button only the ${Value} will change but the p#gaga element remains only one. I know I have left out the buttons pug code, I don't think it is necessary in solving the problem. But if needed will provide it.
I tried doing it using switch statements but I have failed. Hopefully someone can help.
UPDATE & EDIT as requested by https://stackoverflow.com/users/463319/twisty in the comments.
Here is the code: https://jsfiddle.net/YulePale/mdvnf0qt/4/
After doing some research I have made some progress... but I am still stuck.
I am trying to make it in such a way that when I click anywhere outside the gender buttons the input disappears and when I click another button it changes appropriately. Also instead of an input I want to show and hide the template in the html code.
Also, if you don't mind is .data() use to assign or get a value.
PS: Got this code from this answer : Fixing toggle with two buttons
and modified it a bit, but I am still not able to achieve my desired result.
If you review the API for Menu, they have a nice _closeOnDocumentClick(). You can simply use this in your code in a similar way.
Example: https://jsfiddle.net/Twisty/0x43bf8q/
JavaScript
$(function() {
$("input[type='button']").on('click', toggleOptions)
.first()
.trigger('click');
$(document).on("click", function(e) {
if (emptyOnDocumentClick(e)) {
$('[name=gender]').val("");
}
});
function toggleOptions() {
var $this = $(this),
onClass = 'button-toggle-on';
$this.toggleClass(onClass)
.siblings('input[type=button]')
.removeClass(onClass);
var gender = $this.filter('.' + onClass).data('gender');
$('[name=gender]').val(gender);
}
function emptyOnDocumentClick(event) {
return !$(event.target).closest("input[type='button']").length;
}
});
Hope that helps.

Simulate a click() programmatically on a Div

I'm trying to fire an event programmatically. My problem is that I have two SVG on two DIVs and I want to be able to change the border of the DIV I have clicked. To do that I thought to pass the DIV inside my classes and then trigger a click on it once I click on anything. (if there is a better way, please tell me)
I have the following code:
div = querySelector(divName);
svgElement = new svg.SvgSvgElement();
div.append(svgElement);
div.onClick.listen(_setBorders(1));
later I pass the svgElement to another class
ell.show(svgElement);
where show is
show(svg.SvgElement element) {
if (element.parent is DivElement){
_parentDiv= element.parent as DivElement;
element.children.add(_group);
}
}
_parentDiv is of course a DivElement, which I use for an internal onClick()
_onClick(MouseEvent e) {
window.console.info("onClick Ell");
_parentDiv.click();
}
I'm expecting to see the _setBorders(1); I defined with the main div, but it doesn't work. The weird thing is that when I check with the debugger set to the _parentDiv.click() I see that _parentDiv has the event correctly set.
I suppose click() doesn't work as I expected. Any Idea?
If you want that _setBorders(1) is called on click events you have to use :
div.onClick.listen((_) => _setBorders(1));

Resources