I try to build an reservation Form with vaadin 10 while building it i encounterd the problem, that the autocompletion we know from every form on te web doesn't work. I put in an name field the name press submit an the next time i want to re-enter the name i need to write it out again.
My code looks like that (shortend):
TextField name = new TextField();
Button save = new Button("submit");
save.addClickListener(event -> save());
name.setAutocomplete(Autocomplete.ON);
add(name);
add(save);
i had the hopes that Autocomplete.On does the magic for me but it seems not to work. Maybe the way the save methode works screw things up?
the methode is rather big i just simplify it
private void save() {
--save everything to db
--remove all fields
--replace the fields with text saying reservation done
}
found out that someone created issue https://github.com/vaadin/vaadin-text-field/issues/156
seems to be an Shadow DOM limitation
Related issues:
https://bugs.chromium.org/p/chromium/issues/detail?id=746593
https://bugs.webkit.org/show_bug.cgi?id=172567
Edit:
for auto completion for my loginForm i got it working with adding
class xyz extends Div implements PageConfigurator{
...
#Override
public void configurePage(InitialPageSettings settings) {
settings.addInlineWithContents(
InitialPageSettings.Position.PREPEND,
"window.customElements=window.customElements||{};
window.customElements.forcePolyfill=true;
window.ShadyDOM={force:true};",
InitialPageSettings.WrapMode.JAVASCRIPT);
}
I came across this issue recently with Vaadin 14 and a custom login form.
Chrome only offers auto-filling fields (and also save login details) if it can see the input tags with name attributes in the Light DOM, but Vaadin creates TextFields with all of its elements inside of a Shadow DOM hidden.
Solution is to create a reference with <input slot="input"> inside the parent <vaadin-text-field> as part of Light DOM. All the styles and everything will still be in the Shadow DOM but Chrome now can see the input fields for auto-completion.
Kotlin code:
val username = TextField().apply {
element.setAttribute("name", "username")
element.appendChild(Element("input").setAttribute("slot", "input"))
}
val password = PasswordField().apply {
element.setAttribute("name", "password")
element.appendChild(Element("input").setAttribute("slot", "input"))
}
add(username, password)
Related
I have designed the GUI elements and put everything together using CodeName One plugin for Netbeans 8.1. I am first working on my client information GUI that has textfields and a submit button. I'm looking to retrieve the textfield imputs via the submit button action event(I will use the first name textfield as an example:
#Override
protected void onAddRecordGUI_SubmitButtonAction(Component c, ActionEvent event) {
..I tried this
String Fname = findTxt_Firstn(c).getText();
..I also tried this
String FirstName = findTxt_Firstn.getText();
..I then tried this
String FirstName = Txt_Firstn.getText();
}
I get "error: cannot find symbol" with regards to the textfields name (It is correct and located on the same form the button is located)
Am I doing something very wrong here? I found two post on Stack, however, I tried the solutions above anyway.
Okay! I have solved my own questions and this might be applicable to anyone else who encounters this issue. The issue isn't the code, but it is naming textfields with an underscore "_". I renamed the field and was able to create a reference to it.
Thanks.
I made a pretty simple selenium test, where I want to open web page, clear field value, start entering text for this field, select first value from the hint drop down.
Web site is aviasales.com (I just found some site with a lot of controls, this is not an advertisement)
I did
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).clear();
and it was working perfectly, I also checked via console that this is the only one object on a page like:
document.getElementById('flights-origin-prepop-whitelabel_en')
So, in next line I'm sending value:
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).sendKeys("LAX");
but it send LAX value for both "flights-origin-prepop-whitelabel_en" and "flights-destination-prepop-whitelabel_en" for some reason, then i tried
DriverFactory.getDriver().findElement(By.id("//input[#id='flights-destination-prepop-whitelabel_en'][#placeholder='Destination']")).sendKeys(destinationAirport);
but I got the same result:
What could be a reason and how to fix this?
Thank you!
Yep... there's some weird behavior going on there. The site is copying whatever is entered into the first field into the second for reason I don't understand. I gave up trying to understand it and found a way around it.
Whenever I write code that I know I'm going to reuse, I put them into functions. Here's the script code
driver.navigate().to(url);
setOrigin("LAX");
setDestination("DFW");
...and since you are likely to use these repeatedly, the support functions.
public static void setOrigin(String origin)
{
WebElement e = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(origin);
e.sendKeys(Keys.TAB);
}
public static void setDestination(String dest)
{
WebElement e = driver.findElement(By.id("flights-destination-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(dest);
e.sendKeys(Keys.TAB);
}
You can see the functions but basically I click in the field, clear the text (because usually there's something already in there), send the text, and then press to move out of the field and choose the default (first choice).
The reason of your issue is the ORIGIN and DESTINATION inputbox binded keyboard event which used to supply an autocomplete list according to your typed characters.
The binded keyborad event breaks the normal sendKeys() functionality. I met similar case in my projects and questions on StackOverFlow.
I tried input 'GSO' into DESTINATION by sendKeys('GSO'), but I get 'GGSSOO' on page after the sendKeys() complete.
To resolve your problem, we can't use sendKeys(), we have to use executeScript() to set the value by javascript in backgroud. But executeScript() won't fire keyborad event so you won't get the autocomplete list. So we need find out a way to fire keyborady event after set value by javascript.
Below code snippet worked on chrome when i tested on aviasales.com:
private void inputAirport(WebElement targetEle, String city) {
String script = "arguments[0].value = arguments[1]";
// set value by javascript in background
((JavascriptExecutor) driver).executeScript(script, targetEle, city + "6");
// wait 1s
Thread.sleep(1000);
// press backspace key to delete the last character to fire keyborad event
targetEle.sendKeys(Keys.BACK_SPACE);
// wait 2s to wait autocomplete list pop-up
Thread.sleep(2000);
// choose the first item of autocomplete list
driver.findElement(By.cssSelector("ul.mewtwo-autocomplete-list > li:nth-child(1)")).click();
}
public void inputOrigin(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
return inputAirport(target, city);
}
public void inputDestination(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepopflights-destination-prepop-whitelabel_en"));
return inputAirport(target, city);
}
I have been trying to debug why my DropDownChoice in a simple form with just the DropDown and a Submit Button hasn't been working correctly for hours now.
It has a very weird behaviour. Where the first value selected in the drop down choice is sent successfully to the server after which any other choice select is not updated by the model. ie if I have a List persons, and I select the 2nd person, it submits this successfully. However, on select of another person and trying to submit it again it keeps showing the first selected option.
Snippets of code here:
ChoiceRenderer<Empowerment> empowermentChoiceRenderer = new ChoiceRenderer<>("name", "id");
final DropDownChoice<Empowerment> empowermentDropDownChoice =
new DropDownChoice<>("empowerment", new PropertyModel<Empowerment>(this, "empowerment"), empowermentList, empowermentChoiceRenderer);
empowermentDropDownChoice.setRequired(true);
add(empowermentDropDownChoice);
Only way I am able to get a decent behaviour is if I set the empowerment variable above to null. In this case, on submit the empowerment is reinitialised to null and then a new submit works correctly.
empowerment is just a JPA entity.
I'll be glad to know if this is a known issue. I experienced it in wicket 6.9.1 and wicket 6.12
Finally, found the solution to the problem. Above code is correct, but problem lied in the entity class itself - Empowerment needs to implement Equals and Hashcode correctly.
The DropDownChoice works just fine after this.
Add an OnChangeAjaxBehavior to your DropDownChoice. This will update the model value on every selection change you make on the drop down:
empowermentDropDownChoice .add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget art) {
//just model update
}
});
I am brand new to GWT and am trying to achieve the following:
Here's the code that I've cooked up:
public class MyWebApp implements EntryPoint {
// The main container for everything the user sees (the "view")
private LayoutPanel mainPanel;
// Simple HTML for the header ("MyWebApp") and subsequent <hr/>
private SafeHtml header;
// The three links "Dashboard", "Monitors" and "Help Desk"
private HorizontalPanel navMenu;
// The empty content that gets populated when user clicks one of
// the 3 links.
private Panel menuContent;
#Override
public void onModuleLoad() {
// The initial fragment contains the header, nav menu and empty "content" div.
// Each menu/screen then fills out content div.
initMainPanel();
RootPanel.get().add(mainPanel);
}
private void initMainPanel() {
SafeHtmlBuilder headerBuilder = new SafeHtmlBuilder();
navMenu = new HorizontalPanel();
// Leaving null until user clicks on one of the 3 menus.
// Then the menu will decide what panel gets injected for
// this panel.
menuContent = null;
// Create the simple HTML for the header.
headerBuilder.append("<h1>MyWebApp</h1><hr/>");
// Create the navMenu items.
Hyperlink dashboardLink, monitorsLink, helpDeskLink;
// Homepage is http://www.mywebapp.com
// I want the dashboardLink to inject menuContent and "redirect" user to
// http://www.mywebapp.com/dashboard
dashboardLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/monitors
monitorsLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/help-desk
helpDeskLink = new Hyperlink("???", "???");
navMenu.add(dashboardLink);
navMenu.add(monitorsLink);
navMenu.add(helpDeskLink);
// Add all widgets to the mainPanel.
mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
mainPanel.add(navMenu);
mainPanel.add(menuContent);
// Position and size the widgets (omitted for brevity).
// mainPanel.setWidgetHorizontalPosition(...);
}
private HTML getDashboardMenuContent() {
return new HTML("This is the dashboard.");
}
private HTML getMonitorsMenuContent() {
return new HTML("These are the monitors.");
}
private HTML getHelpDeskMenuContent() {
return new HTML("This is the help desk.");
}
}
Most importantly:
How do I "wire up" the Hyperlinks so that when the user clicks them, I can call the appropriate getXXXMenuContent() method, and then add that to menuContent?
But also:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
Thanks in advance!
Hyperlink widgets trigger navigation. You don't want to handle clicks on them, you want to handle navigation (that could be triggered by clicking a Hyperlink or using the browser's back/forward buttons, a bookmark or link from elsewhere –including Ctrl+clicking a Hyperlink to open it in a new window/tab–, etc.)
To react to those navigation events, use History.addValueChangeHandler; and to handle the initial navigation on application start, call History.fireCurrentHistoryState() (after you add your handler of course).
More details in: https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsHistory
Would be better to split other questions to... other questions, but here are the answers anyway:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
The HTML widget has a constructor taking a SafeHtml so you don't need to call toString().
If you're only using a constant, you don't need a SafeHtmlBuilder; use SafeHtmlUtils instead. But constants are no more or less secure with or without SafeHtml, SafeHtml just makes it easier to find all occurrences of HTML in your code, to help in doing a security review of your app (BTW, we're doing HTML, so <hr>, not <hr/>; if you really want it to look like XML/XHTML, then use <hr /> but you're only cheating yourself here)
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
If you don't feel the need for UiBinder, you don't have to use it. But in this case it won't change anything: you're not handling widget events, but history events.
Something like
dashboardLink.addClickHandler(
new ClickHandler()
{
public void onClick( ClickEvent event )
{
mainPanel.setWidget( getDashboardMenuContent() );
}
} );
You should note that Hyperlink.addClickHandler(...) is deprecated and it is recommended to use Anchor.addClickHandler(...) instead.
As for the other questions: It is a lot more elegant and easier to build UI's with UIBinder, so definitely look into that, but do try to make "it" work first to avoid the added complexity of the .ui.xml setup :-)
Cheers,
I have one simple piece of advice to give you. Use what the framework has to offer.
The HTML widget should be your last escape. There are so many widgets that there is no need for you to write html almost anywhere in your code.
So instead of headerBuilder, you can user the following piece of code
Label header = new Label("MyWebApp");
header.setStyleName("headerStyle",true);
You can set the style properties in an external Css file and add the reference inside the base html file or the gwt.xml file. So that answers your question about mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
In respect to the Hyperlink. If you choose to use hyperlinks, remember that the most effective usage is with the MVP pattern better known as Places and Activities (Lots of information on the web)
If you want something simpler instead the MenuBar and MenuItem classes should do the trick.
Look here for an example on how to use the MenuBar to control your application. There are many other ways but why not use the tools provided?
Also the UIBinder Vs the Designer/Classes methods is extensively discussed on stackoverflow resulting to a matter of choice and programming familiarity/preference.
I have been working with a Java applet which is an applet that helps to write using only a mouse. For my case, I am trying to incorporate this into my webiste project as follows:
When the user clicks on any input element (textbox/textarea) on the page, this JAVA applet loads on the webpage itself. In the screenshot of the JAVA applet seen below, the user points to an alphabet to and the corresponding text gets written in the text box of the applet.
Now what I am trying to do is to get this text from the TextBox of the applet to the input element on the webpage. I know that this needs an interaction between the Java and JavaScript, but not being a pro, I really do not have the catch. Here's the Java applet and the code I have written.
Java applet and jQuery code (298kB): http://bit.ly/jItN9m
Please could somebdoy help for extending this code.
Thanks a lot!
Update
I searched somewhere and found this -> To get the text inside of Java text box, a getter method in the Applet to retrieve the text:
public class MyApplet extends JApplet {
// ...
public String getTextBoxText() { return myTextBox.getText(); }
}
In the JQuery code, the following lines are to be added I think:
var textBoxText = $("#applet-id")[0].getTextBoxText();
//Now do something with the text
For the code of the applet, I saw a GNOME git page here. The getText call already exists -- look at the bottom of this file: http://git.gnome.org/browse/dasher/tree/java/dasher/applet/JDasherApplet.java
I'd need to call 'getCurrentEditBoxText' but when should this method 'getCurrentEditBoxText' be called?
In my case, I would probably have to do it when the user clicks in a new input control etc.
You can have full communication between your Applet and any javascript method on the page. Kyle has a good post demonstrating how the Javascript can call the applet and request the text value. However, I presume you want the HTML Textfield to update with each mouse click, meaning the applet needs to communicate with the page. I would modify your javascript to something like this:
var activeTextArea = null;
$('textarea, input').click(function() {
$(this).dasher();
activeTextArea = this;
});
function updateText(text) {
// Careful: I think textarea and input have different
// methods for setting the value. Check the
// jQuery documentation
$(activeTextArea).val(text);
}
Assuming you have the source for the applet, you can have it communicate with the above javascript function. Add this import:
import netscape.javascript.JSObject;
And then, in whatever onClick handler you have for the mouse clicks, add:
// After the Applet Text has been updated
JSObject win = null;
try {
win = (JSObject) JSObject.getWindow(Applet.this);
win.call("updateText", new Object[] { textBox.getText() });
} catch (Exception ex) {
// oops
}
That will update the text each time that chunk of code is called. If you do NOT have access to the applet source, things get trickier. You'd need to set some manner of javascript timeout that constantly reads the value from the applet, but this assumes the applet has such a method that returns the value of the textbox.
See Also: http://java.sun.com/products/plugin/1.3/docs/jsobject.html
Update Modifying the applet is your best shot since that is where any event would be triggered. For example, if you want the HTML TextField to change on every click, the click happens in the applet which would need to be modified to trigger the update, as described above. Without modifying the applet, I see two options. Option #1 uses a timer:
var timer;
var activeTextArea;
$('textarea, input').click(function() {
$(this).dasher();
activeTextArea = this;
updateText();
}
function updateText() {
// Same warnings about textarea vs. input
$(activeTextArea).val($('#appletId')[0].getCurrentEditBoxText());
timer = setTimeout("updateText()", 50);
}
function stopUpdating() {
clearTimeout(timer);
}
This is similar to the code above except clicking on a text area triggers the looping function updateText() which will set the value of the HTML text field to the value of the Applet text field every 50ms. This will potentially introduce a minor delay between click and update, but it'll be small. You can increase the timer frequency, but that will add a performance drain. I don't see where you've 'hidden' the applet, but that same function should call stopUpdating so that we are no longer trying to contact a hidden applet.
Option #2 (not coded)
I would be to try and capture the click in the Applet as it bubbles through the HTML Dom. Then, you could skip the timer and put a click() behavior on the Applet container to do the same update. I'm not sure if such events bubble, though, so not sure if this would work. Even if it did, I'm not sure how compatible it would be across browsers.
Option #3
Third option is to not update the HTML text field on every click. This would simply be a combination of Kyle's and my posts above to set the value of the text field whenever you 'finish' with the applet.
Here's a possible solution. To get the text inside of your Java text box, write a getter method in the Applet to retrieve the text:
public class MyApplet extends JApplet {
// ...
public String getTextBoxText() { return myTextBox.getText(); }
}
In your JQuery code, add the following lines:
var textBoxText = $("#applet-id")[0].getTextBoxText();
//Now do something with the text
I found most of what I posted above here. Hope this helps.
This page explains how to manipulate DOM from a Java applet. To find the input element, simply call the document.getElementById(id) function with id of an id attribute of the text input box.