Wicket form: disable submit button - wicket

In Wicket when I disable a Form instance it perfectly disables my input fields, but it fails to disable the submit button, too.
How to disable the submit button, too, preferable without the need to add wicket:id for the submit button?

Use an AjaxSubmitLink and add it to the form. It will be enabled/disabled along with the form:
HTML:
<button wicket:id="submit">Submit</button>
Java:
form.add(new AjaxSubmitLink("submit"));

I've solved this problem by automatically created Buttons. In my WebApplication's init()-method I install an AbstractMarkupFilter that makes <input type="submit"/> autolinks:
markupSettings.setMarkupParserFactory(new IMarkupParserFactory() {
public MarkupParser newMarkupParser(MarkupResourceStream resource) {
final MarkupParser parser = new MarkupParser(new XmlPullParser(), resource);
parser.appendMarkupFilter(new AbstractMarkupFilter() {
public MarkupElement nextTag() throws ParseException {
final ComponentTag tag = (ComponentTag)getParent().nextTag();
if (tag == null) {
return null;
}
if (tag.getId() != null) {
return tag;
}
if (!tag.isOpen() && !tag.isOpenClose()) {
return tag;
}
if (tag.getName().equals("input") && !(tag instanceof WicketTag)) {
final String type = tag.getAttributes().getString("type");
if ("submit".equals(type)) {
tag.enableAutolink(true);
tag.setId(WicketLinkTagHandler.AUTOLINK_ID);
tag.setAutoComponentTag(true);
tag.setModified(true);
}
}
return tag;
}
};
return parser;
}
});
Then I install an IComponentResolver before the existing AutoLinkResolver:
final List<IComponentResolver> componentResolvers = getPageSettings().getComponentResolvers();
for (int i ; i < componentResolvers.size(); i++) {
final IComponentResolver resolver = componentResolvers.get(i);
if (resolver instanceof AutoLinkResolver) {
componentResolvers.add(i, new IComponentResolver() {
#Override
public boolean resolve(MarkupContainer container, MarkupStream markupStream, ComponentTag tag) {
if (tag.isAutolinkEnabled()) {
if (tag.getName().equals("input")) {
final String type = tag.getAttribute("type");
if ("submit".equals(type)) {
final Page page = container.getPage();
final String autoId = WicketLinkTagHandler.AUTOLINK_ID + Integer.toString(page.getAutoIndex());
if (tag.getId() == null) {
tag.setId(autoId);
tag.setAutoComponentTag(true);
}
container.autoAdd(new Button(autoId));
return true;
}
}
}
return false;
}
});
break;
}
}

Related

AutoCompleteTextField list does not always scroll to top?

The AutoCompleteTextField seems to work exactly as intended until I start backspacing in the TextField. I am not sure what the difference is, but if I type in something like "123 M" then I get values that start with "123 M". If I backspace and delete the M leaving "123 " in the field, the list changes, but it does not scroll to the top of the list.
I should note that everything works fine on the simulator and that I am experiencing this behavior when running a debug build on my iPhone.
EDIT: So this does not only seem to happen when backspacing. This image shows the results I have when typing in an address key by key. In any of the pictures where the list isn't viewable or is clipped, I am able to drag down on the list to get it to then display properly. I have not tried this on an Android device.
EDIT2:
public class CodenameOneTest {
private Form current;
private Resources theme;
private WaitingClass w;
private String[] properties = {"1 MAIN STREET", "123 E MAIN STREET", "12 EASTER ROAD", "24 MAIN STREET"};
public void init(Object context) {
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
}
public void start() {
if(current != null) {
current.show();
return;
}
Form form = new Form("AutoCompleteTextField");
form.setLayout(new BorderLayout());
final DefaultListModel<String> options = new DefaultListModel<>();
AutoCompleteTextField ac = new AutoCompleteTextField(options) {
protected boolean filter(String text) {
if(text.length() == 0) {
options.removeAll();
return false;
}
String[] l = searchLocations(text);
if(l == null || l.length == 0) {
return false;
}
options.removeAll();
for(String s : l) {
options.addItem(s);
}
return true;
};
};
Container container = new Container(BoxLayout.y());
container.setScrollableY(true); // If you comment this out then the field works fine
container.add(ac);
form.addComponent(BorderLayout.CENTER, container);
form.show();
}
String[] searchLocations(String text) {
try {
if(text.length() > 0) {
if(w != null) {
w.actionPerformed(null);
}
w = new WaitingClass();
String[] properties = getProperties(text);
if(Display.getInstance().isEdt()) {
Display.getInstance().invokeAndBlock(w);
}
else {
w.run();
}
return properties;
}
}
catch(Exception e) {
Log.e(e);
}
return null;
}
private String[] getProperties(String text) {
List<String> returnList = new ArrayList<>();
List<String> propertyList = Arrays.asList(properties);
for(String property : propertyList) {
if(property.startsWith(text)) {
returnList.add(property);
}
}
w.actionPerformed(null);
return returnList.toArray(new String[returnList.size()]);
}
class WaitingClass implements Runnable, ActionListener<ActionEvent> {
private boolean finishedWaiting;
public void run() {
while(!finishedWaiting) {
try {
Thread.sleep(30);
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
}
public void actionPerformed(ActionEvent e) {
finishedWaiting = true;
return;
}
}
public void stop() {
current = Display.getInstance().getCurrent();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = Display.getInstance().getCurrent();
}
}
public void destroy() {
}
}
I used this code on an iPhone 4s:
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("AutoComplete", new BorderLayout());
if(apiKey == null) {
hi.add(new SpanLabel("This demo requires a valid google API key to be set in the constant apiKey, "
+ "you can get this key for the webservice (not the native key) by following the instructions here: "
+ "https://developers.google.com/places/web-service/get-api-key"));
hi.getToolbar().addCommandToRightBar("Get Key", null, e -> Display.getInstance().execute("https://developers.google.com/places/web-service/get-api-key"));
hi.show();
return;
}
Container box = new Container(new BoxLayout(BoxLayout.Y_AXIS));
box.setScrollableY(true);
for(int iter = 0 ; iter < 30 ; iter++) {
box.add(createAutoComplete());
}
hi.add(BorderLayout.CENTER, box);
hi.show();
}
private AutoCompleteTextField createAutoComplete() {
final DefaultListModel<String> options = new DefaultListModel<>();
AutoCompleteTextField ac = new AutoCompleteTextField(options) {
#Override
protected boolean filter(String text) {
if(text.length() == 0) {
return false;
}
String[] l = searchLocations(text);
if(l == null || l.length == 0) {
return false;
}
options.removeAll();
for(String s : l) {
options.addItem(s);
}
return true;
}
};
ac.setMinimumElementsShownInPopup(5);
return ac;
}
String[] searchLocations(String text) {
try {
if(text.length() > 0) {
ConnectionRequest r = new ConnectionRequest();
r.setPost(false);
r.setUrl("https://maps.googleapis.com/maps/api/place/autocomplete/json");
r.addArgument("key", apiKey);
r.addArgument("input", text);
NetworkManager.getInstance().addToQueueAndWait(r);
Map<String,Object> result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
String[] res = Result.fromContent(result).getAsStringArray("//description");
return res;
}
} catch(Exception err) {
Log.e(err);
}
return null;
}
I was able to create this issue but not the issue you describe.

Refresh suggestion list on change - cn1 autocomplete

I've implemented a custom autocomplete text field in a cn1 app, but I've noticed it only loads the suggestions list once, after that any change in the text doesn't trigger a change in the list, and the getSuggestionModel() is never called again. How can I achieve this (in my mind, basic) functionality?
This is my autocomplete class:
public class ForumNamesAutocomplete extends AutoCompleteTextField {
List<String>suggestions = new LinkedList<String>();
List<Map<String,Object>> fData;
StateMachine mac;
int currentIndex;
String prevText;
public static final String KEY_FORUM_NAME = "name";
public static final String KEY_FORUM_ID = "id";
public static final String KEY_FORUM_DESC = "desc";
public ForumNamesAutocomplete(StateMachine sm){
super();
mac = sm;
if(sm.forumData != null){
fData = mac.forumData;
}
}
#Override
protected boolean filter(String text) {
if(text.equals(prevText)){
return false;
}
setSuggestionList(text);
fireDataChanged(DataChangedListener.CHANGED, text.length());
prevText = text;
return true;
}
#Override
public void fireDataChanged(int type, int index) {
super.fireDataChanged(type, index);
}
public void setSuggestionList(String s){
if(suggestions == null){
suggestions = new LinkedList<String>();
}else{
suggestions.clear();
}
LinkedList<String> descList = new LinkedList<String>();
for(int i = 0;i<fData.size();i++){
boolean used = false;
Map<String,Object> forumMap = fData.get(i);
if(((String)forumMap.get(KEY_FORUM_NAME)).indexOf(s) != -1){
suggestions.add((String)forumMap.get(KEY_FORUM_NAME));
used = true;
}
if(!used && ((String)forumMap.get(KEY_FORUM_DESC)).indexOf(s) != -1){
descList.add((String)forumMap.get(KEY_FORUM_NAME));
}
}
suggestions.addAll(descList);
}
#Override
protected ListModel<String> getSuggestionModel() {
return new DefaultListModel<String>(suggestions);
}
}
This used to be simpler and seems to be a bit problematic now as explained in this issues.
Technically what you need to do is return one model and then mutate said model/fire modified events so everything will refresh. This is non-trivial and might not work correctly for all use cases so ideally we should have a simpler API to do this as we move forward.
After additional debugging, I saw that the getSuggestionModel() method was being called only during initialization, and whatever the suggestion list (in suggestion object) was at that point, it remained so. Instead I needed to manipulate the underlying ListModel object:
public class ForumNamesAutocomplete extends AutoCompleteTextField {
ListModel<String>myModel = new ListModel<String>();
...
#Override
protected boolean filter(String text) {
if(text.length() > 1){
return false;
}
setSuggestionList(text);
return true;
}
private void setSuggestionList(String s){
if(myModel == null){
myModel = new ListModel<String>();
}else{
while(myModel.getSize() > 0)
myModel.removeItem(0);
}
for(int i = 0;i<fData.size();i++){
boolean used = false;
Map<String,Object> forumMap = fData.get(i);
if(((String)forumMap.get(KEY_FORUM_NAME)).indexOf(s) != -1){
myModel.addItem((String)forumMap.get(KEY_FORUM_NAME));
used = true;
}
if(!used && ((String)forumMap.get(KEY_FORUM_DESC)).indexOf(s) != -1){
myModel.addItem((String)forumMap.get(KEY_FORUM_NAME));
}
}
}
...
}

GWT- In celltable column checkboxcell select all records i want select display record

Frineds,
I am using celltable and their is one column which I put in table header for select all record option and also I am using pager which showing max 15 record in one page. when I clicked on selectall option it will select all records which are present page no 2,3,4,.... in short all records get selected(if total records is 100 it's selected 100 records).so i want only select display page records not all...
ref code is -
final SelectionModel < GenericFirewallRule > selectionModel =
new MultiSelectionModel < GenericFirewallRule > ();
deleteRuleCellTable.setSelectionModel(selectionModel,DefaultSelectionEventManager. < GenericFirewallRule > createCheckboxManager());
// CheckboxCell cbForHeader = new CheckboxCell();
Column < GenericFirewallRule, Boolean > checkColumn = new Column < GenericFirewallRule, Boolean > (
new CheckboxCell()) {#Override
public Boolean getValue(GenericFirewallRule object) {
if(object == null || object.getRuleNumber() == null){
return null;
}else{
if (selectionModel.isSelected(object)) {
if (!ruleListForDelete.contains(object)) {
ruleListForDelete.add(object);
}
} else {
if (ruleListForDelete.contains(object)) {
ruleListForDelete.remove(object);
}
}
System.out.println("ruleListForDelete : " + ruleListForDelete);
return selectionModel.isSelected(object);
}
}
};
Please suggest me solutions....
You can do something like this:
selectAllHeader = new Header<Boolean>(new HeaderCheckbox()) {
#Override
public Boolean getValue() {
for (T item : getVisibleItems()) {
if (!getSelectionModel().isSelected(item)) {
return false;
}
}
return getVisibleItems().size() > 0;
}
};
selectAllHeader.setUpdater(new ValueUpdater<Boolean>() {
#Override
public void update(Boolean value) {
for (T object : getVisibleItems()) {
getSelectionModel().setSelected(object, value);
}
}
});
public class HeaderCheckbox extends CheckboxCell {
private final SafeHtml INPUT_CHECKED = SafeHtmlUtils.fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\" checked/>");
private final SafeHtml INPUT_UNCHECKED = SafeHtmlUtils.fromSafeConstant("<input type=\"checkbox\" tabindex=\"-1\"/>");
public HeaderCheckbox() {
}
#Override
public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
if (value != null && value) {
sb.append(INPUT_CHECKED);
} else {
sb.append(INPUT_UNCHECKED);
}
}
}

LoadException with FXML created with Scene Builder 2.0

I got a problem that i absolutly cant solve on my own because i have just started using JAVA FX. I get a nasty javafx.fxml.LoadException: , but i have done exactly like a guide (http://docs.oracle.com/javafx/scenebuilder/1/get_started/jsbpub-get_started.htm), but i cant get my Main to run. This is the console:
ant -f P:\\FXML\\IssueTrackingLite jfxsa-run
init:
deps-jar:
Created dir: P:\FXML\IssueTrackingLite\build
Updating property file: P:\FXML\IssueTrackingLite\build\built-jar.properties
Created dir: P:\FXML\IssueTrackingLite\build\classes
Created dir: P:\FXML\IssueTrackingLite\build\empty
Created dir: P:\FXML\IssueTrackingLite\build\generated-sources\ap-source-output
Compiling 6 source files to P:\FXML\IssueTrackingLite\build\classes
warning: [options] bootstrap class path not set in conjunction with -source 1.6
1 warning
Copying 4 files to P:\FXML\IssueTrackingLite\build\classes
compile:
Detected JavaFX Ant API version 1.3
Launching <fx:jar> task from C:\Program Files\Java\jdk1.8.0\jre\..\lib\ant-javafx.jar
Warning: From JDK7u25 the Codebase manifest attribute should be used to restrict JAR repurposing.
Please set manifest.custom.codebase property to override the current default non-secure value '*'.
Launching <fx:deploy> task from C:\Program Files\Java\jdk1.8.0\jre\..\lib\ant-javafx.jar
jfx-deployment-script:
jfx-deployment:
jar:
Copying 12 files to P:\FXML\IssueTrackingLite\dist\run910302418
jfx-project-run:
Executing P:\FXML\IssueTrackingLite\dist\run910302418\IssueTrackingLite.jar using platform C:\Program Files\Java\jdk1.8.0\jre/bin/java
before ........!
IssueTrackingLiteController.initialize
août 11, 2014 12:24:01 PM issuetrackinglite.Main start
GRAVE: null
javafx.fxml.LoadException:
file:/P:/FXML/IssueTrackingLite/dist/run910302418/IssueTrackingLite.jar!/issuetrackinglite/IssueTrackingLite.fxml
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2617)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2595)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3230)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3191)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3164)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3140)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3120)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3113)
at issuetrackinglite.Main.start(Main.java:55)
at com.sun.javafx.application.LauncherImpl$8.run(LauncherImpl.java:837)
at com.sun.javafx.application.PlatformImpl$7.run(PlatformImpl.java:335)
at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:301)
at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:298)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$6.run(PlatformImpl.java:298)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NullPointerException
at issuetrackinglite.IssueTrackingLiteController.configureTable(IssueTrackingLiteController.java:481)
at issuetrackinglite.IssueTrackingLiteController.initialize(IssueTrackingLiteController.java:119)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
... 19 more
BUILD STOPPED (total time: 50 minutes 46 seconds)
What does it mean and how can I fix it?
the main class:
package issuetrackinglite;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Application.launch(Main.class, (java.lang.String[])null);
}
#Override
public void start(Stage primaryStage) {
try {
System.out.println(" before ........!");
AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class.getResource("/issuetrackinglite/IssueTrackingLite.fxml"));
System.out.println(" after .............!");
Scene scene = new Scene(page);
primaryStage.setScene(scene);
primaryStage.setTitle("Issue Tracking Lite Sample");
primaryStage.show();
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
my FXML file is in the same path as Main class.
the class Controller:
package issuetrackinglite;
public class IssueTrackingLiteController implements Initializable {
#FXML
Button newIssue;
#FXML
Button deleteIssue;
#FXML
Button saveIssue;
TableView<ObservableIssue> table;
#FXML
TableColumn<ObservableIssue, String> colName;
#FXML
TableColumn<ObservableIssue, IssueStatus> colStatus;
#FXML
TableColumn<ObservableIssue, String> colSynopsis;
#FXML
ListView<String> list;
#FXML
TextField synopsis;
private String displayedBugId; // the id of the bug displayed in the details section.
private String displayedBugProject; // the name of the project of the bug displayed in the detailed section.
#FXML
Label displayedIssueLabel; // the displayedIssueLabel will contain a concatenation of the
// the project name and the bug id.
#FXML
AnchorPane details;
#FXML
TextArea descriptionValue;
ObservableList<String> projectsView = FXCollections.observableArrayList();
TrackingService model = null;
private TextField statusValue = new TextField();
final ObservableList<ObservableIssue> tableContent = FXCollections.observableArrayList();
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rsrcs) {
assert colName != null : "fx:id=\"colName\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert colStatus != null : "fx:id=\"colStatus\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert colSynopsis != null : "fx:id=\"colSynopsis\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert deleteIssue != null : "fx:id=\"deleteIssue\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert descriptionValue != null : "fx:id=\"descriptionValue\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert details != null : "fx:id=\"details\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert displayedIssueLabel != null : "fx:id=\"displayedIssueLabel\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert newIssue != null : "fx:id=\"newIssue\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert saveIssue != null : "fx:id=\"saveIssue\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert synopsis != null : "fx:id=\"synopsis\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert table != null : "fx:id=\"table\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
assert list != null : "fx:id=\"list\" was not injected: check your FXML file 'IssueTrackingLite.fxml'.";
System.out.println(this.getClass().getSimpleName() + ".initialize");
configureButtons();
configureDetails();
configureTable();
connectToService();
if (list != null) {
list.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
list.getSelectionModel().selectedItemProperty().addListener(projectItemSelected);
displayedProjectNames.addListener(projectNamesListener);
}
}
/**
* Called when the NewIssue button is fired.
*
* #param event the action event.
*/
#FXML
public void newIssueFired(ActionEvent event) {
final String selectedProject = getSelectedProject();
if (model != null && selectedProject != null) {
ObservableIssue issue = model.createIssueFor(selectedProject);
if (table != null) {
// Select the newly created issue.
table.getSelectionModel().clearSelection();
table.getSelectionModel().select(issue);
}
}
}
/**
* Called when the DeleteIssue button is fired.
*
* #param event the action event.
*/
#FXML
public void deleteIssueFired(ActionEvent event) {
final String selectedProject = getSelectedProject();
if (model != null && selectedProject != null && table != null) {
// We create a copy of the current selection: we can't delete
// issue while looping over the live selection, since
// deleting selected issues will modify the selection.
final List<?> selectedIssue = new ArrayList<Object>(table.getSelectionModel().getSelectedItems());
for (Object o : selectedIssue) {
if (o instanceof ObservableIssue) {
model.deleteIssue(((ObservableIssue) o).getId());
}
}
table.getSelectionModel().clearSelection();
}
}
/**
* Called when the SaveIssue button is fired.
*
* #param event the action event.
*/
#FXML
public void saveIssueFired(ActionEvent event) {
final ObservableIssue ref = getSelectedIssue();
final Issue edited = new DetailsData();
SaveState saveState = computeSaveState(edited, ref);
if (saveState == SaveState.UNSAVED) {
model.saveIssue(ref.getId(), edited.getStatus(),
edited.getSynopsis(), edited.getDescription());
}
// We refresh the content of the table because synopsis and/or description
// are likely to have been modified by the user.
int selectedRowIndex = table.getSelectionModel().getSelectedIndex();
table.getItems().clear();
displayedIssues = model.getIssueIds(getSelectedProject());
for (String id : displayedIssues) {
final ObservableIssue issue = model.getIssue(id);
table.getItems().add(issue);
}
table.getSelectionModel().select(selectedRowIndex);
updateSaveIssueButtonState();
}
private void configureButtons() {
if (newIssue != null) {
newIssue.setDisable(true);
}
if (saveIssue != null) {
saveIssue.setDisable(true);
}
if (deleteIssue != null) {
deleteIssue.setDisable(true);
}
}
// An observable list of project names obtained from the model.
// This is a live list, and we will react to its changes by removing
// and adding project names to/from our list widget.
private ObservableList<String> displayedProjectNames;
// The list of Issue IDs relevant to the selected project. Can be null
// if no project is selected. This list is obtained from the model.
// This is a live list, and we will react to its changes by removing
// and adding Issue objects to/from our table widget.
private ObservableList<String> displayedIssues;
// This listener will listen to changes in the displayedProjectNames list,
// and update our list widget in consequence.
private final ListChangeListener<String> projectNamesListener = new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
if (projectsView == null) {
return;
}
while (c.next()) {
if (c.wasAdded() || c.wasReplaced()) {
for (String p : c.getAddedSubList()) {
projectsView.add(p);
}
}
if (c.wasRemoved() || c.wasReplaced()) {
for (String p : c.getRemoved()) {
projectsView.remove(p);
}
}
}
FXCollections.sort(projectsView);
}
};
// This listener will listen to changes in the displayedIssues list,
// and update our table widget in consequence.
private final ListChangeListener<String> projectIssuesListener = new ListChangeListener<String>() {
#Override
public void onChanged(Change<? extends String> c) {
if (table == null) {
return;
}
while (c.next()) {
if (c.wasAdded() || c.wasReplaced()) {
for (String p : c.getAddedSubList()) {
table.getItems().add(model.getIssue(p));
}
}
if (c.wasRemoved() || c.wasReplaced()) {
for (String p : c.getRemoved()) {
ObservableIssue removed = null;
// Issue already removed:
// we can't use model.getIssue(issueId) to get it.
// we need to loop over the table content instead.
// Then we need to remove it - but outside of the for loop
// to avoid ConcurrentModificationExceptions.
for (ObservableIssue t : table.getItems()) {
if (t.getId().equals(p)) {
removed = t;
break;
}
}
if (removed != null) {
table.getItems().remove(removed);
}
}
}
}
}
};
// Connect to the model, get the project's names list, and listen to
// its changes. Initializes the list widget with retrieved project names.
private void connectToService() {
if (model == null) {
model = new TrackingServiceStub();
displayedProjectNames = model.getProjectNames();
}
projectsView.clear();
List<String> sortedProjects = new ArrayList<String>(displayedProjectNames);
Collections.sort(sortedProjects);
projectsView.addAll(sortedProjects);
list.setItems(projectsView);
}
// This listener listen to changes in the table widget selection and
// update the DeleteIssue button state accordingly.
private final ListChangeListener<ObservableIssue> tableSelectionChanged =
new ListChangeListener<ObservableIssue>() {
#Override
public void onChanged(Change<? extends ObservableIssue> c) {
updateDeleteIssueButtonState();
updateBugDetails();
updateSaveIssueButtonState();
}
};
private static String nonNull(String s) {
return s == null ? "" : s;
}
private void updateBugDetails() {
final ObservableIssue selectedIssue = getSelectedIssue();
if (details != null && selectedIssue != null) {
if (displayedIssueLabel != null) {
displayedBugId = selectedIssue.getId();
displayedBugProject = selectedIssue.getProjectName();
displayedIssueLabel.setText( displayedBugId + " / " + displayedBugProject );
}
if (synopsis != null) {
synopsis.setText(nonNull(selectedIssue.getSynopsis()));
}
if (statusValue != null) {
statusValue.setText(selectedIssue.getStatus().toString());
}
if (descriptionValue != null) {
descriptionValue.selectAll();
descriptionValue.cut();
descriptionValue.setText(selectedIssue.getDescription());
}
} else {
displayedIssueLabel.setText("");
displayedBugId = null;
displayedBugProject = null;
}
if (details != null) {
details.setVisible(selectedIssue != null);
}
}
private boolean isVoid(Object o) {
if (o instanceof String) {
return isEmpty((String) o);
} else {
return o == null;
}
}
private boolean isEmpty(String s) {
return s == null || s.trim().isEmpty();
}
private boolean equal(Object o1, Object o2) {
if (isVoid(o1)) {
return isVoid(o2);
}
return o1.equals(o2);
}
private static enum SaveState {
INVALID, UNSAVED, UNCHANGED
}
private final class DetailsData implements Issue {
#Override
public String getId() {
if (displayedBugId == null || isEmpty(displayedIssueLabel.getText())) {
return null;
}
return displayedBugId;
}
#Override
public IssueStatus getStatus() {
if (statusValue == null || isEmpty(statusValue.getText())) {
return null;
}
return IssueStatus.valueOf(statusValue.getText().trim());
}
#Override
public String getProjectName() {
if (displayedBugProject == null || isEmpty(displayedIssueLabel.getText())) {
return null;
}
return displayedBugProject;
}
#Override
public String getSynopsis() {
if (synopsis == null || isEmpty(synopsis.getText())) {
return "";
}
return synopsis.getText();
}
#Override
public String getDescription() {
if (descriptionValue == null || isEmpty(descriptionValue.getText())) {
return "";
}
return descriptionValue.getText();
}
}
private SaveState computeSaveState(Issue edited, Issue issue) {
try {
// These fields are not editable - so if they differ they are invalid
// and we cannot save.
if (!equal(edited.getId(), issue.getId())) {
return SaveState.INVALID;
}
if (!equal(edited.getProjectName(), issue.getProjectName())) {
return SaveState.INVALID;
}
// If these fields differ, the issue needs saving.
if (!equal(edited.getStatus(), issue.getStatus())) {
return SaveState.UNSAVED;
}
if (!equal(edited.getSynopsis(), issue.getSynopsis())) {
return SaveState.UNSAVED;
}
if (!equal(edited.getDescription(), issue.getDescription())) {
return SaveState.UNSAVED;
}
} catch (Exception x) {
// If there's an exception, some fields are invalid.
return SaveState.INVALID;
}
// No field is invalid, no field needs saving.
return SaveState.UNCHANGED;
}
private void updateDeleteIssueButtonState() {
boolean disable = true;
if (deleteIssue != null && table != null) {
final boolean nothingSelected = table.getSelectionModel().getSelectedItems().isEmpty();
disable = nothingSelected;
}
if (deleteIssue != null) {
deleteIssue.setDisable(disable);
}
}
private void updateSaveIssueButtonState() {
boolean disable = true;
if (saveIssue != null && table != null) {
final boolean nothingSelected = table.getSelectionModel().getSelectedItems().isEmpty();
disable = nothingSelected;
}
if (disable == false) {
disable = computeSaveState(new DetailsData(), getSelectedIssue()) != SaveState.UNSAVED;
}
if (saveIssue != null) {
saveIssue.setDisable(disable);
}
}
// Configure the table widget: set up its column, and register the
// selection changed listener.
private void configureTable() {
colName.setCellValueFactory(new PropertyValueFactory<ObservableIssue, String>("id"));
colSynopsis.setCellValueFactory(new PropertyValueFactory<ObservableIssue, String>("synopsis"));
colStatus.setCellValueFactory(new PropertyValueFactory<ObservableIssue, IssueStatus>("status"));
// In order to limit the amount of setup in Getting Started we set the width
// of the 3 columns programmatically but one can do it from SceneBuilder.
colName.setPrefWidth(75);
colStatus.setPrefWidth(75);
colSynopsis.setPrefWidth(443);
colName.setMinWidth(75);
colStatus.setMinWidth(75);
colSynopsis.setMinWidth(443);
colName.setMaxWidth(750);
colStatus.setMaxWidth(750);
colSynopsis.setMaxWidth(4430);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setItems(tableContent);
assert table.getItems() == tableContent;
final ObservableList<ObservableIssue> tableSelection = table.getSelectionModel().getSelectedItems();
tableSelection.addListener(tableSelectionChanged);
}
/**
* Return the name of the project currently selected, or null if no project
* is currently selected.
*
*/
public String getSelectedProject() {
if (model != null && list != null) {
final ObservableList<String> selectedProjectItem = list.getSelectionModel().getSelectedItems();
final String selectedProject = selectedProjectItem.get(0);
return selectedProject;
}
return null;
}
public ObservableIssue getSelectedIssue() {
if (model != null && table != null) {
List<ObservableIssue> selectedIssues = table.getSelectionModel().getSelectedItems();
if (selectedIssues.size() == 1) {
final ObservableIssue selectedIssue = selectedIssues.get(0);
return selectedIssue;
}
}
return null;
}
/**
* Listen to changes in the list selection, and updates the table widget and
* DeleteIssue and NewIssue buttons accordingly.
*/
private final ChangeListener<String> projectItemSelected = new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
projectUnselected(oldValue);
projectSelected(newValue);
}
};
// Called when a project is unselected.
private void projectUnselected(String oldProjectName) {
if (oldProjectName != null) {
displayedIssues.removeListener(projectIssuesListener);
displayedIssues = null;
table.getSelectionModel().clearSelection();
table.getItems().clear();
if (newIssue != null) {
newIssue.setDisable(true);
}
if (deleteIssue != null) {
deleteIssue.setDisable(true);
}
}
}
// Called when a project is selected.
private void projectSelected(String newProjectName) {
if (newProjectName != null) {
table.getItems().clear();
displayedIssues = model.getIssueIds(newProjectName);
for (String id : displayedIssues) {
final ObservableIssue issue = model.getIssue(id);
table.getItems().add(issue);
}
displayedIssues.addListener(projectIssuesListener);
if (newIssue != null) {
newIssue.setDisable(false);
}
updateDeleteIssueButtonState();
updateSaveIssueButtonState();
}
}
private void configureDetails() {
if (details != null) {
details.setVisible(false);
}
if (details != null) {
details.addEventFilter(EventType.ROOT, new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (event.getEventType() == MouseEvent.MOUSE_RELEASED
|| event.getEventType() == KeyEvent.KEY_RELEASED) {
updateSaveIssueButtonState();
}
}
});
}
}
}

How to clear autoComplete textfield in Wicket after submit?

I'm having issues clearing the input of a autoComplete Textfield.. For some reason whenever I call target.add(reference to AutoCompleteTextField);
my input values are null...
So basically, I can clear the referenced string the input is stored in, but everytime I call an ajaxupdate it nulls.
I tried both ajaxButton, and AjaxSubmitLink. Both get the same reactions. I have a button to submit the input from the textField.
Code:
<form wicket:id="autoCompleteForm">
<td><input wicket:id="autoCompleteTextField" size="20"/></td>
<td><button width:100px wicket:id="selectRoleBtn">Select</button></td>
</form>
private void autoCompleteForm()
{
findRoleForm = new Form<Void>("autoCompleteForm");
findRoleForm.setOutputMarkupId(true);
addOrReplace(findRoleForm);
field = new AutoCompleteTextField<String>("autoCompleteTextField",
new PropertyModel<String>(this,"autoString"))
{
#Override
protected Iterator<String> getChoices(String input)
{
if (Strings.isEmpty(input))
{
List<String> emptyList = Collections.emptyList();
return emptyList.iterator();
}
List<String> choices = new ArrayList<String>(10);
for (final Role role : rolesList)
{
final String roles = role.getRoleName();
if (roles.toUpperCase().startsWith(input.toUpperCase()))
{
choices.add(roles);
if (choices.size() == 10)
{
break;
}
}
}
return choices.iterator();
}
};
findRoleForm.addOrReplace(field);
findRoleForm.addOrReplace(new AjaxSubmitLink("selectRoleBtn", findRoleForm)
{
protected void onSubmit(AjaxRequestTarget target, Form<?> form)
{
System.out.println("here1" + autoString);
if(rolesList != null && autoString!= null)
{
if(rolesList .size() != 0)
{
for(int i=0; i < rolesList .size(); i++)
{
System.out.println("here2" + autoString);
if(rolesList .get(i).getRoleName().equals(autoString))
{
role = rolesList.get(i);
roleInformation.addOrReplace(new Label("roleNameTxt", role.getRoleName()));
roleInformation.addOrReplace(new Label("roleAliasTxt", role.getRoleAlias()));
roleInformation.addOrReplace(new Label("roleOwnerTxt", role.getRoleOwnerId()));
roleInformation.addOrReplace(new Label("roleStatusTxt", role.getRoleAccessStatus()));
roleInformation.addOrReplace(new Label("roleCategoryTxt", role.getRoleCategoryName()));
roleInformation.addOrReplace(new Label("roleDescriptionTxt", role.getRoleDescription()));
roleInformation.addOrReplace(new Label("roleValidityTxt", role.getRoleValidityStatus()));
roleInformation.addOrReplace(new Label("roleNumUsers", ""));
//add adOrReplace(findRoleForm);
autoString = "";
target.add(field);
target.add(roleInformation);
currentRoleSelection = null;
target.add(rolesDropDownChoice);
break;
}
}
}
}
}
}).add(getIndicatorAppender());
}
Edit:
The autoCompleteTextField input field clears the first time, but when I try it again. The string: autoString will be null. So if you choose your selection on first attempt (from the search list provided), hit select button, it gives you the correct string and clears. But when you do it for a second time, selected a provided value, the "autoString" will be null.. and will not get the input value assigned to it.
Can you describe your problem more properly?
I had to modify your code to get it compiled
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.string.Strings;
public class AutoTestPage2 extends WebPage {
Form<Void> findRoleForm;
AutoCompleteTextField field;
List<Role> rolesList = new LinkedList<AutoTestPage2.Role>();
String autoString;
public AutoTestPage2() {
super();
autoCompleteForm();
}
private void autoCompleteForm() {
rolesList.add(new Role("Adam"));
rolesList.add(new Role("Boris"));
rolesList.add(new Role("Clair"));
findRoleForm = new Form<Void>("autoCompleteForm");
findRoleForm.setOutputMarkupId(true);
add(findRoleForm);
field = new AutoCompleteTextField<String>("autoCompleteTextField",
new PropertyModel<String>(this, "autoString")) {
#Override
protected Iterator<String> getChoices(final String input) {
if (Strings.isEmpty(input)) {
final List<String> emptyList = Collections.emptyList();
return emptyList.iterator();
}
final List<String> choices = new ArrayList<String>(10);
for (final Role role : rolesList) {
final String roles = role.getName();
if (roles.toUpperCase().startsWith(input.toUpperCase())) {
choices.add(roles);
if (choices.size() == 10) {
break;
}
}
}
return choices.iterator();
}
};
findRoleForm.addOrReplace(field);
findRoleForm.addOrReplace(new AjaxSubmitLink("selectRoleBtn", findRoleForm) {
#Override
protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
System.out.println("here1" + autoString);
if (rolesList != null && autoString != null) {
if (rolesList.size() != 0) {
for (int i = 0; i < rolesList.size(); i++) {
System.out.println("here2" + autoString);
if (rolesList.get(i).getName().equals(autoString)) {
final Role role = rolesList.get(i);
// roleInformation.addOrReplace(new Label("roleNameTxt", role.getName()));
//add adOrReplace(findRoleForm);
autoString = "";
target.add(field);
// target.add(roleInformation);
// currentRoleSelection = null;
// target.add(rolesDropDownChoice);
break;
}
}
}
}
}
})/* .add(getIndicatorAppender()) */;
// add(findRoleForm);
}
class Role implements Serializable {
String name;
public Role(final String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
}
and when I press select, text field is cleared and there are two messages in console
here1Adam
here2Adam
I was able to fix this by putting other components inside the same form as the autoCompleteTextField.. for whatever reason, when those are re-rendered and they are inside the form.. it corrects the problem.