As the title above, I want the behaviour of showDialog() to display on a new browser tab but I don't know whether is there any Java code written for that.
My code:
public class ListSportImagesMethod2Action extends TabBaseAction {
private int row;
#Inject
private Tab tab;
public void execute() throws Exception {
Map sportKey = (Map) tab.getTableModel().getObjectAt(row);
//Map sportKey = (Map) getView().getSubview("sport").getValues();
int sportId = ((Integer) sportKey.get("sportId")).intValue();
sportKey.put("sportId", sportId);
showDialog(); //What should it replace with?
getView().setModelName("Sport");
getView().setValues(sportKey); System.out.println("data============" + getView().getValues());
getView().findObject();
getView().setKeyEditable(false);
getView().setEditable(true);
setControllers("Sport");
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public Tab getTab() {
return tab;
}
public void setTab(Tab tab) {
this.tab = tab;
}
}
PS: I know I can use a link to redirect but with this method, I fail to get the parent's data. Am still trying.
showDialog() shows a JavaScript dialog, not a browser windows. showDialog() cannot be used to show something in other browser tab, for that use IForwardAction. IForwardAction goes to a new browser windows, but if you use IForwardAction you have to change all the logic of your action because you redirect to other module that has its own state. The OpenXava documentation explains how to manage this last case.
Related
I have a wicket application on a page we have various forms for the same model split into separate tabs. What I need to do is whenever a tab is clicked check to see if a js variable tabDirty is set to true or false. If it is true I would launch a confirm prompt if okay then reset that form and move to the clicked tab. If cancel stay on that tab with keeping current changes.
I have this js for the warning nothing fancy
function warnOnChange(){
if(tabDirty){
decision = confirm('Leave?');
if(decision){
resetTab(); //sets tabDirty back to false
} else {
return false;
}
}
}
I have a super simple wicket behavior
public class WarnChangePromptOnClickBehavior extends Behavior {
#Override
public void bind(Component component) {
component.add(JQBehaviors.mouseClick(EditMerchant.WARN_ON_CHANGE));
}
}
and that behavior is added to the AjaxFallBackLink
AjaxTabbedPanel<CustomAjaxTab> tabbedPanel = new AjaxTabbedPanel<CustomAjaxTab>("tabbedPanel", tabList, new Model<>(0)) {
private static final long serialVersionUID = 1L;
#Override
protected WebMarkupContainer newLink(final String linkId, final int index) {
AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>(linkId) {
private static final long serialVersionUID = 1L;
#Override
public void onClick(final AjaxRequestTarget target) {
TabbedPanel<CustomAjaxTab> selectedTab = setSelectedTab(index);
CustomAjaxTab tab = tabList.get(index);
if (target != null) {
tab.getPanel(linkId);
target.add(selectedTab);
}
onAjaxUpdate(target);
}
};
link.add(new WarnChangePromptOnClickBehavior());
return link;
}
};
Current behavior with this is that if there is no change the tabs switch no prompt. If there is a change then I get the prompt. If okay tabDirty is reset and go to the next page clearing changes. Issue is that if I click cancel I still navigate to the next tab and lose changes. I know there is something in onClick I need to change but it is just not registering with me.
It is not that easy to intercept the JS event loop, especially when using Ajax requests.
Here is an approach that may do the job:
In warnOnChange() if dirty then call event.preventDefault() and event.stopImmediatePropagation(). This will tell the browser to not follow the link / make an Ajax call. Then show the confirmation dialog as you do now.
If the user presses Cancel then there is nothing more to do
If the use confirms then set dirty to false and do jQuery(event.target).triggerHandler(event.type), i.e. execute the same event (click) on the link. This time it won't be dirty and it will proceed with the Ajax call.
Not sure if this is the appropriate way to do this but I solved my issue like this:
Same old js just slightly modified to return what the user chose:
function warnOnChange(){
decision = true;
if(tabDirty){
decision = confirm('Leave?');
if(decision){
resetTab();
}
}
return decision;
}
Dumped the whole behavior code although I still think it could be used just not sure at the moment...
So to make this all work on the link I override the updateAjaxAttributesof the link with a precondition:
AjaxTabbedPanel<CustomAjaxTab> tabbedPanel = new AjaxTabbedPanel<CustomAjaxTab>("tabbedPanel", tabList, new Model<>(0)) {
private static final long serialVersionUID = 1L;
#Override
protected WebMarkupContainer newLink(final String linkId, final int index) {
AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>(linkId) {
private static final long serialVersionUID = 1L;
#Override
protected void updateAjaxAttributes( AjaxRequestAttributes attributes ) {
super.updateAjaxAttributes( attributes );
AjaxCallListener ajaxCallListener = new AjaxCallListener();
//very important to use the "return" if not then nothing happens with the response
ajaxCallListener.onPrecondition("return " + WARN_ON_CHANGE);
attributes.getAjaxCallListeners().add( ajaxCallListener );
}
#Override
public void onClick(final AjaxRequestTarget target) {
TabbedPanel<CustomAjaxTab> selectedTab = setSelectedTab(index);
CustomAjaxTab tab = tabList.get(index);
if (target != null) {
tab.getPanel(linkId);
target.add(selectedTab);
}
onAjaxUpdate(target);
}
};
link.add(new WarnChangePromptOnClickBehavior());
return link;
}
};
I am using the java framework Vaadin to create a web application. There different user levels for this application, and when the user logs in I change the menu depending on their permission level. The problem I am having is preventing a user from visiting a page they are not suppose to by typing in the URI. For example if a user logs in to the application and only has permission to view page one he can still access page two by typing the URI to page two in the browsers search bar.
I was looking into preventing URI navigation, but was unsuccessful in finding out how this is done in Vaadin. So my question is how to prevent URI navigation in Vaadin? If you have a different method of preventing users from accessing pages they are not suppose to please feel free to post that as well.
So far i've come up short and the one post that i've seen about this on stack overflow does not explain it particularly well.
So far this is what my NavigatorUI class looks like:
#SpringUI
public class NavigatorUI extends UI {
public Navigator navigator;
public static final String LOGIN = "";
public static final String MAINPAGE = "main";
public static final String EMPLOYEEPAGE = "employeepage";
public static final String REGISTERPAGE = "registerpage";
public static final String ADDEMPLOYEEPAGE = "addemployeepage";
public static final String ADDEMPLOYERPAGE = "addemployerpage";
private MainSystem main = new MainSystem();
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
layout.setSpacing(true);
setContent(layout);
Navigator.ComponentContainerViewDisplay viewDisplay = new Navigator.ComponentContainerViewDisplay(layout);
navigator = new Navigator(UI.getCurrent(), viewDisplay);
navigator.addView(LOGIN, new LoginView());
navigator.addView(MAINPAGE, new MainView());
navigator.addView(EMPLOYEEPAGE, new EmployeeView());
navigator.addView(REGISTERPAGE, new RegisterView());
navigator.addView(ADDEMPLOYEEPAGE, new AddEmployeeView());
navigator.addView(ADDEMPLOYERPAGE, new AddEmployerView());
navigator.addViewChangeListener(new ViewChangeListener() {
#Override
public boolean beforeViewChange(ViewChangeEvent event) {
View newView = event.getNewView();
String newViewString= newView.toString();
newViewString = newViewString.substring(0,newViewString.length()-9);
View loginView = new LoginView();
String loginViewString = loginView.toString();
loginViewString = loginViewString.substring(0,loginViewString.length()-9);
boolean result = true;
if (newViewString.equals(loginViewString)){
return result;
}
else if (VaadinSession.getCurrent().getAttribute("role").toString().equals("Admin")||VaadinSession.getCurrent().getAttribute("role").toString().equals("Employee")){
return result;
}
else {
result = false;
}
return result;
}
#Override
public void afterViewChange(ViewChangeEvent event) {
//NO-OP
}
});
}
}
You add a ViewchangeListener to your Navigator instance, that can prevent navigation in the beforeViewChange.
If any listener returns false, the view change is not allowed and afterViewChange() methods are not called.
So you implement that Interface with a check of the current users authorizations against the newView of the event. And in case you want to block that, you return false there.
I have the following ButtonCell. How do I make it respond to a click please (e.g., addClickHandler)? I have tried a number of ways I have found yet none work. None of the Window.alert return a response.
ButtonCell selectButton = new ButtonCell();
Column <HikingMeals,String> update = new Column <HikingMeals,String>(selectButton){
#Override
public String getValue(HikingMeals selectButton)
{
return "Select";
}
public void execute(HikingMeals selectButton) {
// EDIT CODE
Window.alert("Pressed");
}
//#Override
public void update(int index, HikingMeals object, String value) {
// The user clicked on the button for the passed auction.
Window.alert("Pressed2");
}
};
table.addColumn(update, "Select");
You just need to set a FieldUpdater on the update column:
update.setFieldUpdater(new FieldUpdater<HikingMeals, String>() {
#Override
public void update(int index, HikingMeals object, String value) {
Window.alert("Pressed");
}
});
I've got a project written in JavaFX and I'm trying to get a refresh on a tableview without result.
I've googled around and tried some examples I've found but it still doesn't work.
I populate a tableview with information each row in this table can have new comments added to by double click on the row. The a new Tabpane is opened and the new comment can be added there. On close of this tabpane I'd like the one I clicked from to be refreshed.
I must be doing something wrong. I just don't know what.
In my StoreController
private void populateTableView(List<Store> stores) {
ObservableList<Store> data = FXCollections.observableArrayList(stores);
storeNumberColumn.setCellValueFactory(
new PropertyValueFactory<Store, String>("id"));
storePhoneColumn.setCellValueFactory(
new PropertyValueFactory<Store, String>("phoneNbr"));
chainColumn.setCellValueFactory(
new PropertyValueFactory<Store, String>("chainId"));
commentColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Store, ImageView>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Store, ImageView> p) {
Integer numberOfComments = p.getValue().getCommentsCount();
ReadOnlyObjectWrapper wrapper = null;
if (numberOfComments == 0) {
wrapper = null;
} else if (numberOfComments == 1) {
wrapper = new ReadOnlyObjectWrapper(new ImageView(COMMENT_SINGLE_FLAG_SOURCE));
} else {
wrapper = new ReadOnlyObjectWrapper(new ImageView(COMMENT_DOUBLE_FLAG_SOURCE));
}
return wrapper;
}
});
storeTable.setItems(data);
sortTable(storeTable, missedColumn);
}
#FXML
public void handleTableAction(MouseEvent event) {
if (event.getClickCount() == 2) {
showNewCommentStage();
}
}
private void showNewCommentStage() {
initCommentController();
Store store
= storeTable.getSelectionModel().selectedItemProperty().getValue();
commentController.showNewStage(commentPane, store);
}
It seems like the call-function doesn't get called when the commentpane is closed.
CommentController
public void showNewStage(Pane pane, Store store) {
this.store = store;
initStage(pane);
windowHandler = new WindowHandler(stage);
effectHandler.playEffect(pane);
constructCommentHeaders();
List<Comment> comments;
comments = commentService.listByStoreId(store.getId());
populateCommentTable(comments);
}
Like I said I've tried a lot of the solutions found here on Stackoverflow but with no results. The Tableview doesn't refresh. The Stores and the Comments are in different database tables if that's important
Can someone point me in the right direction?
Thanks!
****EDIT****
The Store.class
public class Store extends CommentEntity {
private String id;
private String chainId;
private String phoneNbr;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getChainId() {
return chainId;
}
public void setChainId(String chainId) {
this.chainId = chainId;
}
public String getPhoneNbr() {
return phoneNbr;
}
public void setPhoneNbr(String phoneNbr) {
this.phoneNbr = phoneNbr;
}
#Override
public String toString() {
return "Store{" + "id=" + id + ", chainId=" + chainId + '}';
}
#Override
public String getCommentIdentifier() {
return id;
}
}
The CommentEntity.Class
public abstract class CommentEntity {
private int commentsCount;
public int getCommentsCount() {
return commentsCount;
}
public void setCommentsCount(int commentsCount) {
this.commentsCount = commentsCount;
}
public abstract String getCommentIdentifier();
}
Thank you for input, I hadn't even reflected over the ImageView / String.
Two issues:
First, you need to distinguish between the data the cells in your column are displaying, and the cells that actually display those data. The cellValueFactory determines the data that are displayed. The PropertyValueFactory is a cellValueFactory implementation that references a JavaFX Property, so when you call
storeNumberColumn.setCellValueFactory(new PropertyValueFactory<Store, String>("id"));
it effectively tells the cells in the storeNumberColumn to call the idProperty() method on the Store object in the current row to get the data for the cell. (If no such method exists, it will try to use getId() as a backup plan.)
By default, you get a cellFactory that displays text resulting from calling toString() on the data generated by the cellValueFactory. In the case where your data are simply Strings, this is usually what you need. In other cases, you often need to provide a cellFactory of your own to get the correct way to display the data.
In your case, the data for the commentColumn are simply the number of comments. You are going to display that by choosing an image based on that numeric value.
So you should have
TableColumn<Store, Number> commentColumn = new TableColumn<>("Comments");
For the cellValueFactory, you can just use
commentColumn.setCellValueFactory(new PropertyValueFactory<>("commentsCount"));
Then you need a cellFactory that displays the appropriate ImageView:
commentColumn.setCellFactory(new Callback<TableColumn<Store, Number>, new TableCell<Store, Number>>() {
#Override
public TableCell<Store, Number>() {
private ImageView imageView = new ImageView();
#Override
public void updateItem(Number numberOfComments, boolean empty) {
super.updateItem(count, empty) ;
if (empty) {
setGraphic(null);
} else {
if (numberOfComments.intValue() == 0) {
setGraphic(null);
} else if (numberOfComments.intValue() == 1) {
imageView.setImage(new Image(COMMENT_SINGLE_FLAG_SOURCE));
setGraphic(imageView);
} else {
imageView.setImage(new Image(COMMENT_DOUBLE_FLAG_SOURCE));
setGraphic(imageView);
}
}
}
}
});
The second issue is actually about the update. A TableView keeps its contents "live" by observing JavaFX properties that are provided by the cellValueFactory as ObservableValues. If the value might change while the table is displayed, you must provide an actual property that can be observed: using a ReadOnlyObjectWrapper is no good (because it's read only, so it's wrapped value will not change). The PropertyValueFactory will also return a ReadOnlyObjectWrapper if you do not have JavaFX property accessor methods (i.e. if it is only using getXXX() methods to access the data). So your model class must provide JavaFX Properties.
You can make an immediate fix to this by updating CommentEntity to use an IntegerProperty:
public abstract class CommentEntity {
private final IntegerProperty commentsCount = new SimpleIntegerProperty();
public final int getCommentsCount() {
return commentsCountProperty().get();
}
public final void setCommentsCount(int commentsCount) {
commentsCountProperty().set(commentsCount);
}
public IntegerProperty commensCountProperty() {
return commentsCount ;
}
public abstract String getCommentIdentifier();
}
I would also strongly recommend updating the Store class to use JavaFX Properties in a similar manner.
Trying to make my CellTable Colum sortable but I'm not getting it to work. I'm having an MVP application which gets data from a rest service. To show the data within the table works fine but to sort is doesn't work.
public class LicenseUsageUserViewImpl<T> extends Composite implements LicenseUsageUserView<T> {
#UiTemplate("LicenseUsageUserView.ui.xml")
interface LicenseDataViewUiBinder extends UiBinder<ScrollPanel,LicenseUsageUserViewImpl> {}
private static LicenseDataViewUiBinder uiBinder = GWT.create(LicenseDataViewUiBinder.class);
#UiField
CellTable<GWTLicenseUser> licenseUserCellTable;
List<GWTLicenseUser> licenseUsers;
ListDataProvider<GWTLicenseUser> dataProvider;
public List<GWTLicenseUser> getLicenseUsers() {
return licenseUsers;
}
public void setLicenseUsers(List<GWTLicenseUser> licenseUsers) {
this.licenseUsers = licenseUsers;
}
#UiField Label header;
ListHandler<GWTLicenseUser> sortHandler;
public LicenseUsageUserViewImpl() {
initWidget(uiBinder.createAndBindUi(this));
initCellTable();
}
#Override
public void setLicenseUsersTable(List<GWTLicenseUser> tmpLicenseUsers) {
if (tmpLicenseUsers.isEmpty()) {
licenseUserCellTable.setVisible(false);
} else {
setLicenseUsers(tmpLicenseUsers);
licenseUserCellTable.setWidth("100%");
licenseUserCellTable.setVisible(true);
licenseUserCellTable.setPageSize(getLicenseUsers().size());
licenseUserCellTable.setRowCount(getLicenseUsers().size(), false);
licenseUserCellTable.setRowData(0, getLicenseUsers());
licenseUserCellTable.setVisibleRange(new Range(0, licenseUserCellTable.getRowCount()));
sortHandler.setList(getLicenseUsers());
dataProvider.getList().clear();
dataProvider.getList().addAll(getLicenseUsers());
}
}
#Override
public void initCellTable() {
sortHandler = new ListHandler<GWTLicenseUser>(getLicenseUsers());
licenseUserCellTable.addColumnSortHandler(sortHandler);
licenseUserCellTable.setWidth("100%");
licenseUserCellTable.setVisible(true);
licenseUserCellTable.setVisibleRange(new Range(0, licenseUserCellTable.getRowCount()));
// Create a data provider.
dataProvider = new ListDataProvider<GWTLicenseUser>();
// Connect the table to the data provider.
dataProvider.addDataDisplay(licenseUserCellTable);
licenseUserCellTable.setWidth("100%");
licenseUserCellTable.setAutoHeaderRefreshDisabled(true);
licenseUserCellTable.setAutoFooterRefreshDisabled(true);
// userID
TextColumn<GWTLicenseUser> userIdColumn = new TextColumn<GWTLicenseUser>() {
#Override
public String getValue(GWTLicenseUser object) {
if (object != null ){
return object.getUserId();
} else {
return "NULL";
}
}
};
userIdColumn.setSortable(true);
sortHandler.setComparator(userIdColumn, new Comparator<GWTLicenseUser>() {
#Override
public int compare(GWTLicenseUser o1, GWTLicenseUser o2) {
return o1.getUserId().compareTo(o2.getUserId());
}
});
licenseUserCellTable.addColumn(userIdColumn, "User ID");
// more column entries
licenseUserCellTable.getColumnSortList().push(userIdColumn);
licenseUserCellTable.getColumnSortList().push(countColumn);
licenseUserCellTable.addColumnSortHandler(sortHandler);
}
}
setLicenseUsersTable is called from my activity with the response list of my users. When I start my application and make a rest call my data is provide and put into my list also shown within the CellTable but its not sortable, but I have this sort icon before my colum name. I figured I post the whole code because I think its know easier to see what I'm trying to do.
Thanks for any help.
Remove this line:
sortHandler.setList(getLicenseUsers());
You already passed a List into the SortHandler constructor in
sortHandler = new ListHandler<GWTLicenseUser>(getLicenseUsers());
Also, instead of
setLicenseUsers(tmpLicenseUsers);
you may need to use
licenseUsers.addAll(tmpLicenseUsers);
I hope one of them fixes the problem.