Filters and handlers for FileUpload - gwt

In my GWT project I would like to:
Set a filter for the FileUpload widget so that it only accepts JPG files.
Enable myButton if the FileUpload widget, called chooser, has any file choosen. And disable myButton otherwise.
This is my code for point 2, but it does not work. Any ideas? Thanks in advance!
chooser.addAttachHandler(new Handler() {
public void onAttachOrDetach(AttachEvent event) {
if(chooser.isAttached()==false && myButton.isEnabled()==true)
myButton.setEnabled(false);
else if(chooser.isAttached()==true && myButton.isEnabled()==false)
myButton.setEnabled(true);
} });

I included a line like the one below:
fileUpload.getElement().setAttribute("accept", "image/png, image/gif,image/jpeg");
It did work for me using gwt FileUpload

#Point 1: i think, is not possible to filter, which files can be choosed. The only one way for me is compare in the form handler, for example:
form.addFormHandler(new FormHandler(){
public void onSubmit(FormSubmitEvent event){
if(!extension.equals("pdf")) {
// Error
} else {
// Submit
}
}
}
Another solution is to use ExtGWT with FileValidator:
fileUpload = new FileUploadField();
fileUpload.setWidth("240");
fileUpload.setValidator(new FileValidator());
fileUpload.setName("file");
fileUpload.setAccept("pdf");
#Point 2: the chooser.isAttached() is wrong condition imho....you need to check, if the input field is empty.

Related

How do I clear a wicket AutoCompleteTextField after a choice is selected?

I'm using an AjaxFormComponentUpdatingBehavior to do some stuff when a choice is selected from an AutoCompleteTextField. After that stuff is done I want to clear the field but it's not behaving the way I expected it to.
Here're the relevant bits of code:
final AutoCompleteTextField<String> searchField =
new AutoCompleteTextField<String>(id, model);
searchField.add(new AjaxFormComponentUpdatingBehavior("onchange")
{
#Override
protected void onUpdate(AjaxRequestTarget target)
{
// Do stuff with the selected value here
...
searchField.clearInput();
target.addComponent(searchField);
}
});
I'm putting the value in a ListView and adding that to the target also. It gets updated correctly but the AutoCompleteTextField doesn't.
I think your example doesn't work, because you rerender the component on the client side using the model on the server side. If you reset the model value and repaint the component it has to work.
searchField.setModelObject(null);
target.addComponent(searchField);
However it is not neccessary to render the whole component, just clear the value on server and client side is enough.
The following example clears the model object and reset the field value by javascript (jQuery).
final AutoCompleteTextField<String> searchField =
new AutoCompleteTextField<String>(id, model);
searchField.setOutputMarkupId(true);
searchField.add(new AjaxFormComponentUpdatingBehavior("onchange")
{
#Override
protected void onUpdate(AjaxRequestTarget target)
{
// Do stuff with the selected value here
...
searchField.clearInput();
searchField.setModelObject(null);
target.appendJavascript("$('#" + searchField.getMarkupId() + "').val('');");
}
});
If you are using Wicket prior 6.x then the jQuery is not included. You can use the following JS:
target.appendJavascript("document.getElementById('" + searchField.getMarkupId() + "').value = '';");

How to don't validate form with Ajax buttons

I have a problem with validation on form actually sub-form.
In my website I have some kind of table and "Add row" button (BlockingAjaxSubmitLink).
When I try add let say 2 rows, I get validation error (because row in this table has Required=True parameter) and I can't add another row. I tried use simple AjaxLink but it doesn't have reference to form in onClick method and when I complete some rows and click "Add row" this data get lost.
I want to enable validation only after "save" button click.
Any idea how to deal with this problem?
I do something like you want using an AjaxLink.
My AjaxLink:
private AjaxLink addNewRow = new AjaxLink("addNewRow") {
#Override
public void onClick(AjaxRequestTarget target) {
MyEntityObject newTableRowObject = new MyEntityObject(irrelevantParameter);
entityObjectTableService.createNewRowInDB(newTableRowObject );
target.add(listViewContainer);
}
};
In this code the listViewContainer is a WebMarkupContainer which contains a ListView holding the table rows.
When i click this AjaxLink a new object representing a row in my table is added to the database and then the container containing the ListView is being refreshed refreshing the ListView and the new empty object is being fetched from the DB and shown as a new row in my table at the end.
Depending on your structure maybe you are looking after disabling validation using setDefaultFormProcessing(true); - http://ci.apache.org/projects/wicket/apidocs/6.x/org/apache/wicket/markup/html/form/AbstractSubmitLink.html#setDefaultFormProcessing%28boolean%29
For now I write some kind of hack
First I set
addKnowledgeLink.setDefaultFormProcessing(false);
and next
BlockingAjaxSubmitLink<Object> addKnowledgeLink = new BlockingAjaxSubmitLink<Object>(
"link_knowledge_add") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
ChangeDataForm.this.process(this);
/* some code */
target.add(form.get(MY_CONTAINER_ID));
}
(...)
and my hack...
//HACK
public void process(IFormSubmitter object){
if (!isEnabledInHierarchy() || !isVisibleInHierarchy())
{
return;
}
// run validation
validate();
/*if (hasError())
{
// mark all children as invalid
markFormComponentsInvalid();
// let subclass handle error
callOnError(object);
}
else
{*/
// mark all children as valid
markFormComponentsValid();
// before updating, call the interception method for clients
beforeUpdateFormComponentModels();
// Update model using form data
updateFormComponentModels();
// validate model objects after input values have been bound
onValidateModelObjects();
if (hasError())
{
callOnError(object);
return;
}
// Form has no error
delegateSubmit(object);
//}
}
and I ovveride one method
#Override
protected void onError(){
super.onError();
this.updateFormComponentModels();
}
I know it is ugly solution but I couldn't figure out anything better..
And I couldn't shutdown feedback messages

hovering HTML help page over a link in GWT

I'm trying to implement a hovering HTML help page over a link or widget in a GWT GUI.
I tried to do something similar to change image on hover using gwt and ui-binder and http://examples.roughian.com/index.htm#Listeners~PopupListener
ui.xml
<layout:cell horizontalAlign="LEFT">
<widget:ButtonLink ui:field="manageApps" text="Applications"/>
</layout:cell>
ui.java
PopupPanel popup = new PopupPanel(true);
HTML html = new HTML("<p>Hello</p>");
//popup.setStyleName("demo-popup");
popup.add(html);
#UiHandler("manageApps")
public void onMouseOver(MouseOverEvent event) {
popup.center();
}
However compilation fails on the #UiHandler with the message: Field manageApps doesn't have 'addHandler' method for com...MouseOverHandler.
Any idea or pointer helps. Thanks.
I have a solution so far that can be improved later:
ui.java
#Override
public void onMouseOver(MouseOverEvent mouseOverEvent) {
//To change body of implemented methods use File | Settings | File Templates.
popup.center();
}
manageApps.addHandler(this, MouseOverEvent.getType());
What is a ButtonLink? If you made it yourself, did you implement HasMouseOverHandlers? Chances are the problem is that the widget doesn't know how to throw a MouseOverEvent, but you're trying to catch them anyway.
I have a solution so far that can be improved later:
ui.java
#Override
public void onMouseOver(MouseOverEvent mouseOverEvent) {
//To change body of implemented methods use File | Settings | File Templates.
popup.center();
}
manageApps.addHandler(this, MouseOverEvent.getType());

Block gwt DisclosurePanel on open state

How may I block a gwt DisclosurePanel on the open state ?
I mean, how can I prevent this DisclosurePanel to close if the user click the header more than once ?
(My header is a textBox, I want the user to enter a text, and the panel should remain open if the user unfocus the textBox and focus newly by clicking it. The DisclosurePanel content has a "cancel" button that closes the panel)
Thank you very much.
I edit my question after 2 first answers: I would like to avoid to reopen the DisclosurePanel once closed to avoid flashing effect. I actually want to prevent the DisclosurePanel to close. Maybe sinkEvents can help me... if so, how? Thanks.
A NativePreviewHandler receives all events before they are fired to their handlers. By registering a nativePreviewHandler the first time your disclosurePanel is opened, you can cancel the click event. You can later decide to remove this handler by preventClose.removeHandler();
HandlerRegistration preventClose = null;
....
panel.addOpenHandler(new OpenHandler<DisclosurePanel>() {
#Override
public void onOpen(OpenEvent<DisclosurePanel> event) {
if (preventClose == null){
preventClose = Event.addNativePreviewHandler(new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (event.getTypeInt()==Event.ONCLICK && event.getNativeEvent().getEventTarget() == panel.getHeader().getElement().cast())
event.cancel();
}
});
}
}
});
The obvious answer is review the javadoc here: https://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/user/client/ui/DisclosurePanel.html
There is a setOpen() method that: Changes the visible state of this DisclosurePanel.
Set it to false from a click event to capture the user action.
The JavaDoc is right here: https://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/user/client/ui/DisclosurePanel.html
jamesDrinkard pointed the old 1.5 javadoc.
You can use the addCloseHandler(CloseHandler<DisclosurePanel> handler) method to add a handler so when the user tries to close it you can reopen it again with setOpen().
Maybe not the best way, but it worked for me (maybe just one of both will work too):
dPanel.setOpen(true);
dPanel.addOpenHandler(new OpenHandler<DisclosurePanel>() {
#Override
public void onOpen(OpenEvent<DisclosurePanel> event) {
dPanel.setOpen(true);
}
});
dPanel.addCloseHandler(new CloseHandler<DisclosurePanel>() {
#Override
public void onClose(CloseEvent<DisclosurePanel> event) {
dPanel.setOpen(true);
}
});

How can I predict which Wicket components will have their tags rendered in the final page?

For some Wicket components, if I call setOutputMarkupId(true) they warn when they are rendered.
Markup id set on a component that is usually not rendered into markup.
I'd like to output an id for every component that will actually end up in the HTML in order that I can find them with XPath for testing. How can I predict from class or properties of a Component whether it is sensible to setOutputMarkupId(true)?
More detail - in my Application I'm overriding
protected void init() {
super.init();
addComponentInstantiationListener(new IComponentInstantiationListener() {
public void onInstantiation(Component component) {
if (!(component instanceof WebMarkupContainer)) return;
if (component instanceof WebMarkupContainerWithAssociatedMarkup) return;
if (component instanceof Border.BorderBodyContainer) return;
WebMarkupContainer container = (WebMarkupContainer) component;
if (container.isTransparentResolver()) return;
component.setOutputMarkupId(true);
}});
For a sample of pages, this arbitrary gubbins does the trick, but it does seem pretty arbitrary!
Repeater components like DataView and ListView don't have their own markup, but repeat the markup with Items. You can check if the component is instanceof RepeatingView.
This problem is easily shown by the following, wrong, example:
ListView<Person> people = new ListView<Person>("people", list) {
protected void onPopulateItem(ListItem<Person> item) {
add(new Label("name", item.getModelObject().getName()));
}
}
Here we don't add the label to the list item, but rather the listview. And that fails. The code should've been:
ListView<Person> people = new ListView<Person>("people", list) {
protected void onPopulateItem(ListItem<Person> item) {
item.add(new Label("name", item.getModelObject().getName()));
}
}
Also ignore auto-components (Component.isAuto()).
Such components are for example: <wicket:container>, <wicket:enclosure>, etc.
This is just an idea. I didn't try this ans can't right now...
You could find the components, that will propably be rendered by checking if the are tied to a WicketTag (which are not rendered or at least which are the ones causing this message).
This can be done like this:
boolean isGoingToBeRendered (Component component) {
MarkupStream stream = new MarkupStream(component.getMarkup());
ComponentTag tag = stream.getTag();
return (!tag instanceof WicketTag);
}
Again: This is no tried solution, just some lines of code hacked into this editor. It's indended as a pointer not as a ready to use piece of code.