JSF2.0: How to write h:form in MyComponent in Java? - java

I'm writing a JSF2.0-component as a Java class and Renderer class and so on. I can't write parts of the output in the xhtml like
<h:outputText ... />
because the elements are generated dynamically.
So I get the message "The button/link/text component needs to have a Form in its ancestry. Please add .".
Below you can see how I currently render a form. Is this correct too? Or should change something to make the warning dissappear?
private void encodeForm(Element elem) throws IOException {
//ResponsWriter writer
writer.startElement("form", form);
encodeChildren(elem);
writer.endElement("form");
}
Is it possible to connect an input-field to a variable that is created during runtime (i.e. an Object in a List)? If yes how? If no: I have to implement the decode()-method right?
How should I render a button that submits such a form? It should for example call a method
in my component that then somehow (how? like the decode-method?) can process the user-input.
Thanks for any help!

Is this correct too? Or should change something to make the warning dissappear?
Your best bet would be to just remove the code you've shown and ask the users of said component to place it inside a form.
At any length, what you're doing is writing markup for a form. This is something else than actually putting a form component in the tree.

Related

Is there a way to call an anchor after a Context Menu Item is clicked?

Im trying to download a file using the anchor and a context menu. I need to create the anchor dynamically, so that means I need to call a function, before the anchor gets called.
I already tried the following:
this.ctmFilesGrid.addItem(" Download", click -> {
if(click.getItem().isPresent()) {
this.fDownloadingFile = click.getItem().get();
this.createDownloadingAnchor();
this.ancFileDownloader.getElement().callJsFunction("click");
}
}).addComponentAsFirst(FontAwesome.Solid.FILE_DOWNLOAD.create());
But the anchor isnt called.
I hope someone can help me with that.
Thanks in advance
You can't start a download from a server-side event listener, no. The browser will block this; it's a security limitation. This is because there's no way to link the "click" function call to the original user event, and all downloads must be directly initiated by the user.
The proper solution would probably be something like a custom Servlet or a RequestHandler that handles the generation of the content. Do also check https://vaadin.com/directory/component/lazy-download-button for ideas.

GWT Hyperlink strange behavior - redirecting to http://localhost:8080/#

Okay, this is very strange.
All I am having is a Hyperlink in my menu:
Hyperlink eventCalendar= new Hyperlink("Eventkalender", "eventCalendar=" + store.getId());
and I am listening to the ValueChangeEvent in the MainViewPresenter. Please notice that I am not doing anything. Right before the creation of the listener I am setting a SimplePanel to be the display for the ActivityManager:
App.activityManager.setDisplay(this.mainView.getMainContentContainer());
History.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
GWT.log("onValueChange() historyToken " + historyToken);
}
});
But if I click the link what happens is this:
First, for the blink of an eye I can see the browser URL change to
http://localhost:8080/#eventCalendar=1
but it changes immediately back to
http://localhost:8080/#
which causes my landing page to get loaded inside the SimplePanel which I declared as display (see above).
Does anybody have an idea what could cause this behavior because this does not make sense to me? Why does the URL get changed again? Am I using History or Hyperlink wrong?
Most probably your PlaceHistoryMapper returns null for the eventCalendar=1 token, so it's replaced with the default place you gave to the PlaceHistoryHandler. If you're using GWT.create() based on PlaceTokenizers, with a factory and/or #WithTokenizers, that means either you don't have a PlaceTokenizer for the empty-string prefix (#Prefix("")), or that one tokenizer returns null.
That being said, you probably should rather try to use places directly rather than going through the history. That means using a ClickHandler on some widget and calling PlaceController#goTo with the appropriate place. Ideally, that widget would be an Anchor whose href is computed from the result of getToken from your PlaceHistoryMapper with the given place (how the href actually looks depends on your Historian; if you stick to the default behavior, then just prepend a # to the returned token).

how to forward back to JSP page without losing the data entered in fields?

I have a simple MVC-based JSP application. Something like:
*.jsp -> ControllerServlet -> *Command.java -> *Service.java -> *DAO.java -> Oracle db
A typical link in the application looks like this:
myapp/controller?cmd=ShowEditUser&userid=55
Which causes ShowEditUserCommand.java execute() method to run and will forward to editUser.jsp
In editUser.jsp, they fill in the fields, then click Save which posts to myapp/controller?cmd=ModifyUser which runs ModifyUserCommand.java execute() method which modifies the user data and forwards to viewUser.jsp.
Everything works fine.
The problem is, in ModifyUserCommand.execute() I'm checking to see if the username is unique. If they try to enter a username that already exists, I set an error value to true and errorMessage value to Already in use.
Then because of the error I forward to the original editUser.jsp (not viewUser.jsp) and the error is displayed above the form.
MY PROBLEM IS (finally! ;) -- when the user is returned to editUser.jsp with the error message displayed, the data they entered in the fields is all blanked out. How can I set it so whatever they entered in the fields is still in place?
Any suggestions or advice are greatly appreciated!
Rob
Simplest way would be to pass the form fields back to your editUser.jsp in your forward action in ModifyUserCommand.execute(). You can do that with individual parameters i.e.
editUser.jsp?field1=1&field2=2
Alternatively, you could pass data with other methods - i.e. encoded JSON.
You can then process your fields in your editUser.jsp via the page's request object and set your form field values accordingly.
There may be other ways to do this depending on what underlying framework (if any) you are using. But this is a basic way of approaching it.

How to wire up GWT hyperlink click handler?

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.

Bridge between the Java applet and the text input controls on the web page

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.

Categories