How to reload a vaadin tabpage from another one - java

I'm using a tabcontainer in my webpage. In one of the tabpages, I'm adding some data to a table. In another tabpage I'm dynamically generating buttons according to same table. However, the inserted or deleted changes are not shown in that page; there are no new buttons for new values or disappeared buttons for deleted records. I'm using Vaadin Push both as an annotation and as manually. I'm also refilling the table on tabpage change:
public MainTabContainer(){
//...
tabshtMain.addSelectedTabChangeListener(new SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
event.getTabSheet().getSelectedTab().setEnabled(true);
event.getTabSheet().getSelectedTab().requestRepaintAll();
if (event.getTabSheet().getSelectedTab() == steril) {
steril.fillTables();
tabshtMain.markAsDirty();
steril.markAsDirty();
getUI().push();
}
});
}
}
And here is the code sample where I generate buttons for the records in class of tabpage:
private MHorizontalLayout buildMHorizontalLayout_3() {
horizontalLayout_3 = new MHorizontalLayout();
horizontalLayout_3.setImmediate(true);
horizontalLayout_3.setWidth("100.0%");
horizontalLayout_3.setHeight("-1px");
horizontalLayout_3.setMargin(false);
for (StrMachine strMchn : listGrp.keySet()) {
MButton btnMakine = new MButton();
btnMchn.setImmediate(true);
btnMchn.setWidth("80px");
btnMchn.setHeight("80px");
btnMchn.setCaption(Icon.CREDIT_CARD.variant(IconVariant.SIZE_4X));
btnMchn.setHtmlContentAllowed(true);
btnMchn.setId(strMchn.getCode());
btnMchn.addClickListener(btnMchnClickListener);
horizontalLayout_3.addComponent(btnMchn);
horizontalLayout_3.setComponentAlignment(btnMakine, new Alignment(48));
}
return horizontalLayout_3;
}
To solve the issue I've made controls 'immediate' and called requestRepaintAll() bu they didn't help. Only refreshing page is working though.
Sorry for my language and missing jargons of sof. If you have any solutions or suggestions for the problem, please advise me.
Thanks

Related

saving nodes created by user on JavaFX GUI

enter image description hereI made a GUI on JavaFX that's for creating timetables. when I open the app I can add plans (Buttons) to day columns (VBox). ofc the changes aren't saved after I close the app: the next time I open it the table is empty.
my question is how can I make it save nodes that the user creates so the next time i open the app they're there?
this is the exact part where the nodes get added for what it's worth:
void ask_add_plan(ActionEvent event)
{
Button b = (Button) event.getSource();
VBox v = (VBox) b.getParent();
AnchorPane pop_up = new AnchorPane(); //this pop up is to specify things about the plan
//but i removed unnecessary code for simplicity
VBox pop_up_v = new VBox();
Button add = new Button("Add");
add.setOnAction(e->{
Button plan = new Button(what_to_do.getText());
v.getChildren().add(plan);
container.getChildren().remove(pop_up); //container is the anchor pane everything's in
});
pop_up_v.getChildren().add(add);
pop_up.getChildren().add(pop_up_v);
container.getChildren().add(pop_up); //container is the anchor pane everything's in
}
The JavaFX nodes are just the presentation of your data. They are not meant to be saved. Store the actual data itself in a private field in your class.
In your Application.stop method, write the data to a file.
In your Application.start method, read that file and use it to rebuild JavaFX nodes.
private static final Path PLANS_FILE =
Path.of(System.getProperty("user.home"), "plans.txt");
private final List<String> plans = new ArrayList<>();
void ask_add_plan(ActionEvent event) {
// ...
add.setOnAction(e -> {
String planText = what_to_do.getText();
plans.add(planText);
Button plan = new Button(planText);
v.getChildren().add(plan);
container.getChildren().remove(pop_up);
});
}
#Override
public void start(Stage primaryStage)
throws Exception {
// ...
if (Files.exists(PLANS_FILE)) {
plans.addAll(Files.readAllLines(PLANS_FILE));
// Add UI elements for each stored plan.
for (String planText : plans) {
Button planButton = new Button(planText);
v.getChildren().add(planButton);
container.getChildren().remove(pop_up);
}
}
}
#Override
public void stop()
throws IOException {
Files.write(PLANS_FILE, plans);
}
The above is just a simplified example. The file doesn’t have to store just strings.
I get the impression that the data created in the application is more complex than just plan strings. For complex data, XML may be more a suitable file format. Or you can use Java serialization. Or, you can invent your own file format.
You also don’t have to read from and write to a file. You can use a database, if you’re comfortable with database programming. Or you can use Preferences (though Preferences are not well suited to storing lists of complex data).
You should use MVP (model-view-presenter) pattern. Saving data in UI layer is not a good practice. Create a model with data and then serialize it.

Wicket - Set Model from another panel

I am quite new to Wicket. I am adding a model to a sub-panel(ChartPanel) from a main panel (MainPanel) on a button click.
MainPanel.java
On button click, I am re-adding the chartPanel after I change its model. Following is the code I am using in the buttonClick of the MainPanel. Here the onRenderAnnotations event is generated on some click in the UI.
#OnEvent
public void onRenderAnnotations(RenderAnnotationsEvent aEvent)
{
LOG.trace("clicked on the annotation");
renderChart( aEvent.getRequestHandler());
}
private void renderChart(IPartialPageRequestHandler aRequestHandler)
{
MultiValuedMap<String, Double> recommenderScoreMap = getLatestScores(aRequestHandler);
Map<String,String> curveData = new HashMap<String,String>();
LearningCurve learningCurve = new LearningCurve();
for (String recommenderName : recommenderScoreMap.keySet()) {
String data = recommenderScoreMap.get(recommenderName).stream().map(Object::toString)
.collect(Collectors.joining(", "));
curveData.put(recommenderName,data);
learningCurve.setCurveData(curveData);
learningCurve.setMaximumPointsToPlot(MAX_POINTS_TO_PLOT);
}
chartPanel.setDefaultModel(Model.of(learningCurve));
// to avoid the error, A partial update of the page is being rendered
try {
aRequestHandler.add(chartPanel);
}
catch (IllegalStateException e) {
LOG.warn("Not updating the chart. " + e.toString());
setResponsePage(getPage());
}
}
ChartPanel.java
After this in the chartPanel, I want to use the updated model to add component inside the chartpanel. What would be the best way to do that?
I want to do something like this in the class ChartPanel:
#Override
protected void onRender()
{
super.onModelChanged();
LearningCurve newLearningCurve = getModel().getObject();
requestTarget = ???
String js = createJavascript(newLearningCurve);
requestTarget.prependJavascript(js);
}
My question is, in the above code how to get the request target since it is not an ajax request neither do I get it in the arguments. Should I use some other function where I also get a requestTarget. But I want it to be called every time the model of ChartPanel is updated from anywhere.
Pardon my ignorance. I have been trying for a few days but I am still stuck. I tried to explain it enough but if any information is missing, please comment and I will add it right away.
Thanks.
You should override renderHead() instead:
#Override
public void renderHead(IHeaderResponse response)
{
super.renderHead(response);
response.render(OnLoadHeaderItem.forScript(
createJavascript(newLearningCurve)));
}
This way your chart will be shown correctly regardless whether it was added due to an AjaxRequest or simply when the page is rerendered.

GXT : Cancel click event on grid header

I have a grid like this one . The default behavior of this widget is to sort the column when clicking on the header. I want to disable that, and leave only the options in the context menu.
grid.addHeaderClickHandler(new HeaderClickHandler() {
#Override
public void onHeaderClick(HeaderClickEvent event) {
event.getEvent().cancelBubble(true);
event.getEvent().preventDefault();
event.getEvent().stopPropagation();
Window.alert("Event caught");
}
});
The alert gets displayed before the sorting. But when clicking Ok the default behavior kicks in.
Do you have any suggestions on how to accomplish this?
A solution that might work is to use the NativePreviewHandler, something similar to
Event.addNativePreviewHandler(new NativePreviewHandler()
{
#Override
public void onPreviewNativeEvent(final NativePreviewEvent event)
{
if (event.getTypeInt() == Event.ONCLICK)
{
Element targetElement = Element.as(event.getNativeEvent().getEventTarget());
if (!tableHeader.asWidget().getElement().isOrHasChild(targetElement))
{
event.getNativeEvent().stopPropagation();
}
}
}
});
In order to disable sorting you have to configure the column(s) to forbid sorting.
E.g. if you create a column like this (based on the source code from http://www.sencha.com/examples/#ExamplePlace:basicgrid)
ColumnConfig<Stock, String> symbolCol = new ColumnConfig<Stock, String>(props.symbol(), 100, "Symbol");
disable sorting by adding
symbolCol.setSortable(false);
See http://dev.sencha.com/deploy/gxt-3.0.0/javadoc/gxt/com/sencha/gxt/widget/core/client/grid/ColumnConfig.html#setSortable%28boolean%29 for documentation (and other options).
Ok I found it grid.getView().setSortingEnabled(false);. This will disable the sorting when clicking on the header, but keep the menu items in place.

Is it possible to nest forms in Wicket that are independent of each other?

Is it possible to nest forms in Wicket that are independent of each other? I want to have a form with a submit button and a cancel button. Both buttons should direct the user to the same page (let's call it Foo). The submit button should send some info to the server first; the cancel button should do nothing.
Here's a really simplified version of my existing code:
Form form = new Form() {
public void onSubmit()
{
PageParameters params = new PageParameters();
params.put("DocumentID", docID);
setResponsePage(Foo.class, params);
}
};
DropDownChoice<String> ddc = new DropDownChoice<String>("name", new PropertyModel<String>(this, "nameSelection"), names);
ddc.setRequired(true);
final Button submitButton = new Button("Submit") {
public void onSubmit() { doSubmitStuff(true); }
};
final Button cancelButton = new Button("Cancel") {
public void onSubmit() { doSubmitStuff(false); }
};
form.add(ddc);
form.add(submitButton);
form.add(cancelButton);
form.add(new FeedbackPanel("validationMessages"));
The problem is, I just added a validator, and it fires even if I press the cancel button, since the cancel button is attached to the same form as everything else. This could be avoided if the cancel button were in a separate form. As far as I know, I can't create a separate form because — due to the structure of the HTML — the separate form would be under the existing form in the component hierarchy.
Can I make the forms separate somehow in spite of the hierarchy? Or is there some other solution I can use?
EDIT:
In response to Don Roby's comment, this is a bit closer to what my code looked like back when I was trying setDefaultFormProcessing():
Form<Object> theForm = new Form<Object>("theForm") {
public void onSubmit()
{
PageParameters params = new PageParameters();
params.put("DocumentID", docID);
setResponsePage(Foo.class, params);
}
};
final CheckBox checkbox = new CheckBox("checkbox", new PropertyModel<Boolean>(this, "something"));
checkbox.add(new PermissionsValidator());
theForm.add(checkbox);
final Button saveButton = new Button("Save") {
public void onSubmit()
{ someMethod(true); }
};
final Button cancelButton = new Button("Cancel") {
public void onSubmit()
{ someMethod(false); }
};
cancelButton.setDefaultFormProcessing(false);
theForm.add(saveButton);
theForm.add(cancelButton);
theForm.add(new FeedbackPanel("validationMessages"));
There is an even simpler solution: call the setDefaultFormProcessing method on the cancel button with false as a parameter:
cancelButton.setDefaultFormProcessing(false);
This way, clicking the cancel button will bypass the form validation (and model updating), directly calling the onSubmit function.
It is possible to "nest" forms in wicket.
See this wiki entry
for some notes on how it works and this wiki entry for how it interacts with validation.
But for what you're after, the answer from Jawher should have worked and is much simpler.
Look at this example code for hints on getting that working.
I'm wondering if you've simplified your code too far in this posting. Can you produce a sample small enough to post that definitely has the problem?

Wicket: Can I use a modal Panel with a AjaxFallbackButton?

I have 2 inputs. When I press a button(AjaxFallbackButton), those inputs are saved into database.
If one of the input is greater than 10, when I press the button, I want to show a modal panel, for asking the user if is the sure about his option. But the modal component is not appearing. Any thoughts?
#Override
public void onSubmit(AjaxRequestTarget target) {
if (input < 10) { //save to database
} else {
AskingDialogPanel panel = new AskingDialogPanel("content",
new ResourceModel("asking.title"),
new ResourceModel("asking.message")) {
#Override
public void onOkClick(AjaxRequestTarget target) {
super.onOkClick(target);
//save to database
modalWindow.close(target);
}
#Override
public void onCancelClick(AjaxRequestTarget target) {
super.onCancelClick(target);
modalWindow.close(target);
}
};
panel.setOutputMarkupId(true);
target.addComponent(panel);
modalWindow.setContent(panel);
modalWindow.show(target);
}
Have a look at the documentation for the AjaxRequestTarget.
A component whose markup needs to be
updated should be added to this target
via
AjaxRequestTarget#addComponent(Component)
method. Its body will be rendered and
added to the envelope when the target
is processed, and refreshed on the
client side when the ajax response is
received.
I'm not sure if I remember this correctly (I've had trouble implementing the correct refresh behavior previously), but I believe you could only addComponent components that were previously added to the page, but not rendered / invisible. These will than be updated and/or their visibility re-evaluated.
I could be wrong however.. Does the above work if you substitute a normal Label for the AskingDialogPanel? (Just to verify I'm talking out the wrong end ;))

Categories

Resources