h:commandLink conditional target - java

I have a h:commandLink :
<h:commandLink value=""
actionListener="#{controller.authenticateAccount}"
style="text-decoration: none;"
target="#{controller.userNameGiven ? '_parent' : '' }">
<img src="../images/Profile/authenticateCPButton.gif" border="0" style="padding-left: 2px;"/>
</h:commandLink>
Now controller.userNameGiven is a boolean field and is set to true if username given and otherwise set to false. The h:commandLink is present in a iframe and prior to this the target was set to _parent and then if the username is present then it was redirecting to a page in the same parent window but in other case the iframe was rendered in the parent page which is clearly a bug. Now after the target validation the redirected page is opening in that iframe, which is undesirable. What I am doing wrong?
Thanks and regards.
Edit 1:
I have changed the target to:
target="#{controller.target}"
where:
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
and
if(this.userName != null && this.userName.trim().length()>0) {
target = "_parent";
FacesContext.getCurrentInstance().getExternalContext().redirect("./somepage");
} else {
target = "";
}
But its still not working and the url somepage is opening in the iframe.

Move the logic into a bean method:
public class Controller
{
// ...
public boolean isUserNameGiven () { /* snip */ }
public String getFooTarget()
{
return this.isUserNameGiven() ? "_parent" : "";
}
// ...
}

Related

How to clear the RootPanel before displaying the next view

I am using GWT Java and I am trying to remove the PayPal Donate button (i.e., clear the RootPanel), which is part of an HTML form, when I move from the LoginView to another view. I found that I should use:
RootPanel.get("payPalDonate").clear();
RootPanel.get().clear();
RootPanel.get().getElement().setInnerHTML("");
This does clear the form so it does not appear on the next view; however, when the next view is displayed the buttons, hyperlinks and the browser back button on the view do not work.
The code is in the :
private void checkWithServerIfSessionIdIsStillLegal(String sessionID) {
rpc = (DBConnectionAsync) GWT.create(DBConnection.class);
ServiceDefTarget target = (ServiceDefTarget) rpc;
String moduleRelativeURL = GWT.getModuleBaseURL() + "MySQLConnection";
target.setServiceEntryPoint(moduleRelativeURL);
AsyncCallback<Account> callback = new AuthenticationHandler<Account>();
rpc.loginFromSessionServer(callback);
}
class AuthenticationHandler<T> implements AsyncCallback<Account> {
#Override
public void onFailure(Throwable caught) {
RootPanel.get().add(new LoginView());
}
#Override
public void onSuccess(Account result) {
if (result == null) {
RootPanel.get().add(new LoginView());
} else {
//if (result.getLoggedIn()) {
RootPanel.get().clear();
//RootPanel.get().add(new SelectPersonView());
RootPanel.get().add(new LoginView());
//} else {
//RootPanel.get().add(new LoginView());
//}
}
}
}
public void onValueChange(ValueChangeEvent<String> event) {
RootPanel.get("payPalDonate").clear();
RootPanel.get().clear();
RootPanel.get().getElement().setInnerHTML("");
//Get the historyToken value
String historyToken = event.getValue();
//Check the historyToken
if (historyToken.startsWith("!"))
historyToken = historyToken.substring(1);
if (historyToken.length() == 0) {
//Initial entry
RootPanel.get().clear();
RootPanel.get().add(new LoginView());
} else if (historyToken.equals("login")) {
RootPanel.get().clear();
RootPanel.get().add(new LoginView());
} else if (historyToken.equals("goToVideo")) {
RootPanel.get().clear();
Window.Location.replace("https://www.youtube.com/user/GlyndwrBartlett");
} else if (historyToken.equals("goToMetawerx")) {
RootPanel.get().clear();
Window.Location.replace("https://www.metawerx.net/");
} else if (historyToken.equals("goToPrivacy")) {
RootPanel.get().clear();
RootPanel.get().add(new SecurityAndPrivacyView());
} else if ...
In the LoginView:
initWidget(verticalPanel);
RootPanel.get("payPalDonate");
In the html:
<div style="margin:auto" id="payPalDonate">
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="image" src="https://www.paypalobjects.com/en_AU/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_AU/i/scr/pixel.gif" width="1" height="1">
</form>
</div>
Typically in GWT the RootPanel is never cleared. When you start your app, you pass a container to the RootPanel, and then all the views are added to and removed from that container.
Personally, I use Activities and Places pattern for all of my apps. This link offers an example of how to change views within a main container.
I am reading the link provided by Andrei. In the meantime I found the issues were being cased by:
RootPanel.get().getElement().setInnerHTML("");
I tried:
RootPanel.getBodyElement().removeChild(RootPanel.get("payPalDonate").getElement());
However, this cased the same issue. In the end I found this https://groups.google.com/forum/#!topic/google-web-toolkit/zVvY39blkY4
So I replaced the offending code with:
RootPanel.get("payPalDonate").setVisible(false);
And I placed the code in the LoginView just before I pass control to another view. Not the most elegant; however, it works until I digest the information provided by Andrei.

Showing specific error in JSP with Ajax

I'm trying to show in my App different errors when a user is already logged in and when the user wrote their username/password wrong. I have tried many ways but none of them is working. I don't know what else to try or if it's even possible. I don't know if I'm close to the solution either.
What I'm trying to do is:
Set the errorMessage in the request;
Set the SC_INTERNAL_SERVER_ERROR in the response so the AJAX function enters in ** and the HTML in the paramether is the one in the JSP with the specific Message.
Action
public class LogUser extends Action {
#Override
public void execute() throws Exception {
...
String pageToGo = this.tryLogUser(username, password);
request.getRequestDispatcher(pageToGo).forward(request, response);
}
private String tryLogUser(String username, String password) throws Exception {
String pageToGo = "page/userHome";
...
if(canLog) {
...
try {
...
Server.getInstance().logIn(user); // Throws an Exception if the User is already logged in.
...
} catch (ServerException e) {
this.setErrorMessage("That user is already logged in.");
pageToGo = "page/error.jsp";
}
} else {
this.setErrorMessage("User and/or Password are incorrect.");
pageToGo = "page/error.jsp";
}
return pageToGo;
}
private void setErrorMessage(String message) {
request.setAttribute("errorMessage", message);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
JSP
<div class="alert alert-danger"> ${ requestScope.errorMessage } </div>
AJAX
function showUserHome() {
$.post( "${ sessionScope.ServletUrl }", $( "form#logForm" ).serialize() )
.done(function( html ) {
$( "div#toolbar" ).load("page/userToolbar.jsp");
$( "div#content" ).html( html );
})
.fail(function( html ) {
$( "#result" ).html( html );
});
}
Edit:
While trying to Debug it from the browser, it gets in the $.post and after that step, it jumps to the end of the function, skipping .done and .fail and the page remains the same. I'm not getting any error in the RAD Console or the Browser Console other than the SC_INTERNAL_SERVER_ERROR that I setted on the Action.
Calling setErrorPage method won't change your pageToGo local variable and thus always the same view is used. Change it to something like:
pageToGo = setErrorPage("That user is already logged in.");
(or even consider rename it to getErrorPage)

a4j:support onchange event not firing

I'm trying to rerender a second dropdown when i change the value in the first one.
But nothing happens when I click and change the value in the first drop down.
Have I missed any crucial part?
My xhtml:
<h:form>
<h:selectOneMenu value="#{adminBean.currentLeadCategory}" required="true" styleClass="formfield fpgeo" style="width:20em;margin-right:20px;">
<a4j:support event="onchange" action="#{adminBean.currentLeadCategoryChanged()}"
reRender="componentToReRender"/>
<s:selectItems value="#{leadCategories}" var="leadCategory" label="#{leadCategory.name}" noSelectionLabel="Choose Category"/>
<s:convertEntity/>
</h:selectOneMenu>
<a4j:outputPanel id="componentToReRenderWrapper">
<h:selectOneMenu id="componentToReRender" value="#{adminBean.currentCounty}"
styleClass="formfield fpgeo" style="width:20em;margin-right:20px;">
<s:selectItems value="#{adminBean.counties}" var="county" label="#{county.name}" noSelectionLabel="choose"/>
<s:convertEntity/>
</h:selectOneMenu>
<h:messages/>
</a4j:outputPanel>
</h:form>
My bean:
#AutoCreate
#Scope(ScopeType.CONVERSATION)
#Name("adminBean")
#MeasureCalls
#Restrict("#{s:hasRole('admin') or s:hasRole('sales')}")
public class AdminBean implements Serializable {
private LeadCategory currentLeadCategory;
private List<County> counties = new ArrayList<County>();
private County currentCounty;
#Factory(value = "leadCategories", autoCreate = true, scope = ScopeType.SESSION)
public List<LeadCategory> fetchLeadCategories() {
Query query = entityManager.createQuery("select l from LeadCategory l");
return query.getResultList();
}
public LeadCategory getCurrentLeadCategory() {
return currentLeadCategory;
}
public void setCurrentLeadCategory(LeadCategory currentLeadCategory) {
this.currentLeadCategory = currentLeadCategory;
}
public County getCurrentCounty() {
return currentCounty;
}
public void setCurrentCounty(County currentCounty) {
this.currentCounty = currentCounty;
}
public void currentLeadCategoryChanged() {
this.loadCountiesForCategory();
}
public List<County> getCounties() {
return counties;
}
public void setCounties(List<County> counties) {
this.counties = counties;
}
public void loadCountiesForCategory(){
if(currentLeadCategory == null){
counties = new ArrayList<County>();
}
counties = new ArrayList<County>(currentLeadCategory.getCounties());
}
}
EDIT 1:
If i check firebug i get an error:
Timestamp: 7/19/12 4:14:44 PM
Error: ReferenceError: A4J is not defined
Source File: http://localhost:8080/admin/admin.seam?cid=11
Line: 1
Ok found the problem! Major crazyness going on here. Someone has set LoadScriptStrategy
param to NONE in the web.xml. This makes that the framework.pack.js and ui.pack.js is NOT loading.
<context-param>
<param-name>org.richfaces.LoadScriptStrategy</param-name>
<param-value>NONE</param-value>
</context-param>
Found this page at docs.jboss
If you use the "NONE" strategy, you must include the following scripts
in your portlet or portal page header. If you are using JBoss Portal,
you can add this to the jboss-portlet.xml file.
Added <a4j:loadScript src="resource:///org/ajax4jsf/framework.pack.js"/>
to my header template and viola everything works like a charm.
I love my job =)
I can see clearly that your xhtml has an ending tag </a4j:outputPanel> but no starting tag: <a4j:outputPanel>
If you rearrange your tags it will work.

Tapestry 5, jQuery UI Dialog and close action

Using tapestry5-jquery and Dialog component, ¿How do I implement a close action for the parent dialog?. I mean a button that executes some code and then close parent dialog without changing of page.
This is the javascript only version of what I'm doing:
<div id="container">
¿Are you sure to delete selected items?
</div>
$('#container').dialog({
modal : true,
buttons:[{
text: "Yes",
click: function() {
//Perform action here, then close dialog.
$(this).dialog("close");
}
},{
text: "No",
click: function() {
//Only close dialog
$(this).dialog("close");
}
}
}]
});
But I need to use Tapestry 5 tags and java class methods:
<t:jquery.dialog t:clientId="delDialog">
¿Are you sure to delete selected items?
<input t:type="submit" t:id="delYes" value="Yes"/>
<input t:type="submit" t:id="delNo" value="No"/>
</t:jquery.dialog>
Java class:
public class UserAdmin {
#OnEvent(component = "delYes", value = EventConstants.SELECTED)
void delYesClicked(){
//Delete selected items
}
#OnEvent(component = "delNo", value = EventConstants.SELECTED)
void delNoClicked(){
//Close dialog
}
}
Thanks.
You could do something like this if the clientId is always the same (i.e. 'delDialog')
#Inject
private AjaxResponseRenderer ajaxResponseRenderer;
protected void addCloseDialogCommand() {
ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
#Override
public void run(JavaScriptSupport javascriptSupport) {
javascriptSupport.addScript("$('#delDialog').dialog('close');");
}
});
}
...and call the method in your event handler:
#OnEvent(component = "delNo", value = EventConstants.SELECTED)
void delNoClicked() {
addCloseDialogCommand();
}
This behavior could be implemented using a mixin that you apply on any element you want.
Suggested mixin:
public class DialogButtonHandler {
#Parameter(value = "dlgId", defaultPrefix = BindingConstants.LITERAL)
private String dlgId;
#Inject
private JavaScriptSupport javaScriptSupport;
#InjectContainer
private ClientElement element;
#AfterRender
public void afterRender() {
javaScriptSupport.addScript(
"$('#%s').click(function(){$('#%s').dialog('close');});",
element.getClientId(), dlgId);
}}
Markup:
<t:jquery.dialog t:clientId="delDialog">
¿Are you sure to delete selected items?
<input t:type="submit" t:id="delYes" value="Yes" />
<input t:type="submit" t:id="delNo" value="No" t:mixins="dialogButtonHandler" t:dlgId="delDialog"/>
</t:jquery.dialog>

Multiple File Uploads - JSF

I am using JSF 1.2 framework. Right now i am trying to implement a file upload process in which the number of files to be uploaded is controlled by the end user. Please find the below snapshot and code snippet for reference.
XHTML Implementation:-
<a4j:commandLink action="#{importWSDLBean.xsdLoopIncrementAction}" reRender="WSDLPanelGrid">
<h:graphicImage value="/images/plus_icon.gif" />
</a4j:commandLink>
<a4j:commandLink action="#{importWSDLBean.xsdLoopDecrementAction}" reRender="WSDLPanelGrid">
<h:graphicImage value="/images/minus_icon.gif" />
</a4j:commandLink>
<h:panelGrid id="WSDLPanelGrid">
<c:forEach items="#{importWSDLBean.acscDataList}" var="inputFUpload">
<t:inputFileUpload id="#{inputFUpload.id}" value="#{inputFUpload.value}" />
</c:forEach>
</h:panelGrid>
Java Bean Implementation:-
public String xsdLoopIncrementAction() {
if (acscDataList == null) {
acscDataList = new ACSCDataList(new ArrayList());
HtmlInputFileUpload htmlUpload = new HtmlInputFileUpload();
htmlUpload.setId("upload" + (acscDataList.size() + 1));
acscDataList.add(htmlUpload);
} else {
HtmlInputFileUpload htmlUpload = new HtmlInputFileUpload();
htmlUpload.setId("upload" + (acscDataList.size() + 1));
acscDataList.add(htmlUpload);
}
return "success";
}
public String xsdLoopDecrementAction() {
if (acscDataList != null) {
if (acscDataList.size() > 0) {
acscDataList.remove(acscDataList.size() - 1);
}
}
return "success";
}
This implementation resets the file upload values whenever i increment or decrement the no. of file upload fields. Also when i submit the form i cant able to get the UploadedFile object (File Upload prerequisite such as Form type and Web.xml configuration is also included).
Can anyone help me out?
If you create dinamically yours input uploads? with binding property
<h:panelGrid binding="#{importWSDLBean.myPanelGrid}"></h:panelGrid>
in your backing bean add property
private javax.faces.component.html.HtmlPanelGrid myPanelGrid;
/**
* #return the myPanelGrid
*/
public javax.faces.component.html.HtmlPanelGrid getMyPanelGrid() {
return myPanelGrid;
}
/**
* #param myPanelGrid the myPanelGrid to set
*/
public void setMyPanelGrid(javax.faces.component.html.HtmlPanelGrid myPanelGrid) {
this.myPanelGrid = myPanelGrid;
}
/*change for your value upload type*/
Map<String,Object> values = new LinkedHashMap<String, Object>();
public void addInputAction() {
String key = "key"+values.size();
values.put(key,"newValue");
HtmlInputText input = new HtmlInputText();
/*add input property (converter,css,etc?)*/
input.setId("id_"+key);
input.setValueExpression("value", createValueExpression(
"#{WSDLPanelGrid.values['"+key+"']}", new Class[0], String.class));
/*add to panel grid your input*/
myPanelGrid.getChildren().add(input);
}
public static ValueExpression createValueExpression(String value,
Class[] params, Class returnType) {
FacesContext fctx = FacesContext.getCurrentInstance();
ELContext elctx = fctx.getELContext();
Application jsfApp = fctx.getApplication();
ExpressionFactory exprFactory = jsfApp.getExpressionFactory();
ValueExpression valueExpr = exprFactory.createValueExpression(elctx,
value, returnType);
return valueExpr;
}
Does something prevent you from using JSF 2? Primefaces ( www.primefaces.org ) has a multiple fileupload component. It is available for JSF 1.2, but development will go on for JSF 2 only.

Categories

Resources