(Wicket) Change visibility during ajax response - java

I have a AjaxPagingNavigator. Basically on a certain condition, the list which the AjaxPagingNavigator pages is reloaded. When this happens I only want to render the navigator when the list contains more than 1 page.
So does anyone know where I can attach a handler so that I can check for a visibility condition in my AjaxPagingNavigator and enable/disable visibility so that when the navigator is updated via. ajax it is either visible or not?
Markup:
<div wicket:id="mainWrap">
<div wicket:id="navigator"/>
<div wicket:id="listWrap">
<div wicket:id="list><!-- here be content --></div>
</div>
</div>
So I have an ajax event which refreshes "mainWrap" which refreshes the "navigator" along with the "list" and wrappings.
this is the event that triggers the whole thing.
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
List foo = null; // do work to get list
model.setFound(found); // update the model (thus updating "list")
target.addComponent(mainWrap);
}
Edit: I know I can write
navigator.setVisibility(list.getPageCount() > 1);
after creating the navigator and after updating the model, but I was hoping to encapsulate that in a subclass of AjaxPagingNavigator.

Be careful with doing expensive computations in an overridden isVisible method, as Wicket will call isVisible multiple times per request—not counting any calls you might inadvertently do.
Typically the best way to go about this is to override onConfigure and set the visibility flag manually.
#Override
void onConfigure() {
super.onConfigure();
setVisible(isVisible() && someExpensiveToCalculateCondition);
}
onConfigure is called just once during request processing, and called for all components, including those that are invisible (while onBeforeRender is only called for visible components).

It's been a while since I touched Wicket, but if memory serves:
Can you not override the isVisible() method of your "navigator" object, such that it only displays under the condition you desire?
e.g. something like
.addComponent(new AjaxPagingNavigator(...) {
#Override public boolean isVisible() {
return model.getFound().size() > 25;
}
});

Related

How to retrieve and modify HTML content from WebView with Http Post

I'm developing an android app that shows some part of a HTML page. For the first step, I use this code provided in question How to retrieve HTML content from WebView.
Full html picture
That part i want to show
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
#SuppressWarnings("unused")
public void processHTML(String html)
{
// process the html as needed by the app
}
}
final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
browser.getSettings().setJavaScriptEnabled(true);
/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
/* This call inject JavaScript into the page which just finished loading. */
browser.loadUrl("javascript:window.HTMLOUT.processHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
}
});
/* load a web page */
browser.loadUrl("http://example.com/gethtml.html");
but when a user click on a button in second picture a HTTP post method will be called and this will be the result HTML
my question is how retrieve and modify the Post Result Html before showing to user? and show something like this
A simple solution could be to inject custom css code inside your webview, changing the style of the HTML element you want to display "alone".
You should inject a css like this:
#central-box {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
// depends on the structure of the page
}
See also in this answer for an example of how to do it.
There are at least three ways to do this that I can think of and you're really close to all of them:
You already have a rough idea of the quick and dirty method, from #lifeisfoo, although to handle both GET and POST pre-API 21 you would need to use onPageCommitVisible(WebView view, String url). As onPageFinished(WebView view, String url) and shouldOverrideUrlLoading (WebView view, String url) only trigger on GET requests.
Here's why, straight from the SDK...
..."onPageCommitVisible callback can be used to determine the point at which it is safe to make a recycled WebView visible, ensuring that no stale content is shown. It is called at the earliest point at which it can be guaranteed that onDraw(Canvas) will no longer draw any content from previous navigations. The next draw will display either the background color of the WebView, or some of the contents of the newly loaded page." it's called on all content updates POST or GET.
Slightly better, you can create a local proxy web page with the javascript interface and other fun bits already in place and stored as a resource, if the content you want is loaded into full-window iframe you can get really good control, you can interact with your proxy using onPageFinished since it's in an iframe you can interact with the target page using onLoadResource, handle interception using the old shouldInterceptRequest which returns a WebResourceResponse and deal with POST driven updates using onFormResubmission.
Finally, If API support earlier than 21 isn't a big issue the best method would be to use the new shouldInterceptRequest which takes the new WebResourceRequest object that allows you to specify different handling for different request types.
Here's the API Links for the new WebResourceRequest object and the new shouldInterceptRequest method on the WebViewClient...
http://developer.android.com/reference/android/webkit/WebResourceRequest.html
http://developer.android.com/reference/android/webkit/WebViewClient.html#shouldInterceptRequest(android.webkit.WebView, android.webkit.WebResourceRequest)
hope that helps :)

Printing an error message on screen using Wicket

So, I got a wicket page with some components I can update, and some of them updates automatically.
this.getFieldOneInput().add(new AjaxFormComponentUpdatingBehavior("onchange") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
Panel.this.populateFieldTwo(target);
Panel.this.populateFieldThree(target);
}
});
There is an auto complete feature so I can fill my field on with available objects from DB. And every time i change my field one value, I will also populate fields two and three.
But I need to do something else here. I need to check if the chose object for field on got some null valued attribute. If any of its attribute is null, I want to show an error message on screen: "FieldOne attribute X is null". I want it to be shown on screen like those red wicket messages when some field is required.
How can I do that?
By using the Wicket FeedbackPanel
HTML:
<div wicket:id="feedback"></div>
Page:
Add a new FeedbackPanel, and just do error(message)
Reference: http://www.wicket-library.com/wicket-examples/compref/wicket/bookmarkable/org.apache.wicket.examples.compref.FormPage?0

GWT History - Why does it change the focus of my screen?

I have a simple application structure that will contain three composites at any one time - my header, footer and content composites. The composites are laid out in the follow manner.
<body>
<div id="header">
<div id="content">
<div id="footer">
</body>
The composites are assigned to the three <div>'s in my EntryPoint. The EntryPoint also contains a History Handler as follows.
History.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
if(historyToken.isEmpty()) {
parseTokens();
ContentContainer.INSTANCE.setContent(new IndexScreen());
}
else if(historyToken.equalsIgnoreCase("registration")) {
ContentContainer.INSTANCE.setContent(new RegisterScreen());
}
else if(historyToken.equalsIgnoreCase("login")) {
ContentContainer.INSTANCE.setContent(new LoginScreen());
}
}
});
History.fireCurrentHistoryState();
In my Composites, I have several ClickEvent handlers that look similar to the following.
#UiHandler("registerLink")
public void handleClick(ClickEvent event) {
ContentContainer.INSTANCE.setContent(new RegisterScreen());
History.newItem("registration", true);
}
This registers the history very nicely. It also brings me to the appropriate pages when I click the back button. However, it has the very odd effect of focusing the browser on the content composite, with the effect of the browser being scrolled to the bottom. It's not a deal breaker but it kind of breaks the user experience a little. (Do let me know if the explanation isn't clear, I'll add images)
What exactly is causing this and how can I fix it?
GWT history tokens work with the hash # token. In html this was originally intended to use the browser to focus on a specific part of the page, if an element has a name or id with the string after the # token. Could it be you have an id matching your history token?
Also in you handleClick you call setContent. But if I'm correct the call after it triggers a change event and will end up in the onValueChange, which also calls the setContent. So it looks like you are calling setContent twice here.

How to have a subview create a new view every time it is rendered

I have a JSF page that contains two subviews. Depending on which commandButton is executed, one of the subviews is rendered. However, if validation fails on one of the subviews, the error messages stay visible and the components are still invalid the next time the subview is rendered. I have a workaround in my bean to remove the messages but the components stay invalid. Is there a way to set the components as valid or create a new view for the subview only?
Here is my work around for the messages:
Iterator messageIterator = FacesContext.getCurrentInstance().getMessages();
while (messageIterator.hasNext())
{
messageIterator.remove();
}
This is caused by the fact that when rendered is false the component is not shown, but it still is in the component tree for the view. So the component does not show but its values and state are still there.
There are several ways around this:
Use JSTL tags such as <c:if /> (if at all possible) instead of rendered. Page elements inside a <c:if/> tag will be in the tree only if the condition is true.
Don't do a postback when passing from one subview to the other. This effectively recreates the tree from scratch. For example perform a GET instead of a POST.
Invalidate the view so that the tree is recreated. Make the commandButton that switches subviews immediate="true" and invalidate the view adding this code:
public void clearComponentTree() {
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ViewHandler viewHandler = application.getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, context.getViewRoot().getViewId());
context.setViewRoot(viewRoot);
context.renderResponse();
}
Directly manipulate the component tree deleting unwanted components (similar to the above, but limited to specific components). Here I assume we want to delete all components under a subview with id sub1 (this requires immediate="true" as well):
public void clearSubtree() {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().findComponent(":sub1").getChildren().clear();
}
this link provides other minor ways of achieving this.
Try using primefaces extension: resetInput to reestablish the input's state:
<p:commandButton value="Load Subview" action="#{bean.startSubview}" update="subview" process="#this" >
<pe:resetInput for="subview"/>
</p:commandButton>

GWT adding Event Handler overrides the native one?

lets say i have the following html element on my host page:
<input type="text" onfocus="this.value = ''" id="textField"/>
In gwt i wrap this into an TextBox Widget like this:
final TextBox myTextBox = TextBox.wrap(DOM.getElementById("textField"));
If i now want to add a focus handler what will happen?
myTextBox.addFocusHandler(new FocusHandler() {
public void onFocus(final FocusEvent event) {
// do something
}
});
What i want to achieve is that first the javascript which was defined on the host page should be executed and after that my focus handler should be executed. But what actually is happening is that the javascript from the hostpage is not being executed and only the code within onFocus is executed. Is this behavoir normal? I would expect that add means actually add and not override. Is there a way to work arround this? Or do i maybe have any flaws which induce this behavoir. Any help is appreceated.
kuku

Categories