Hi
I am creating checkboxes dynamically, so just wanted to know how to pass request attribute to <html:checkbox /> tag.
Eg: request.setAttribute("counter_1", false);
how to set it in below code snippet.
<html:checkbox property=? />
<html:checkbox /> is struts 1.x tag and to get the value from request attribute using jstl you can use below code snippet
<html:checkbox property="${counter_1}" />
You should create ActionForm with your properties like
public class YourForm extends ActionForm {
private boolean counter;
// getters, setters
}
Then declare your form in the struts config. And after that:
<html:checkbox property="counter" />
Related
I'm learning Spring boot. I have a list of products with unique ids, and I want to implement a "lookup by id" functionality, but I don't know how to do it, I searched but got totally different stuff.
I already have a #Getmapping method like this:
#Getmapping(/products/{id})
If I manually type in the id in the url I'll get what I what. But I want to have an input box in the HTML page like:
<form>
Look up by id: <input/>
</form>
and after I submit the form it'll redirect to that page. For example, if I enter input of 1, it'll go to localhost:8080/products/1
I've been searching but all I got was stuff about #Postmapping.
Add a #PostMapping to your controller:
#Controller
#RequestMapping("/products")
public class ProductController {
#GetMapping //Controller method for showing the empty form
public String index(Model model) {
model.addAttribute("formData", new SearchFormData()); // Create an empty form data object so Thymeleaf can bind to it
return "index";
}
#PostMapping
public String searchById(SearchFormData formData) {
return "redirect:/products/" + formData.getId(); //Use the value the user entered in the form to do the redirect
}
#GetMapping("/{id}")
public String showProduct(#PathVariable("id") long id) {
...
}
}
With SearchFormData representing the form fields (there is only 1 field in this case):
public class SearchFormData {
private long id;
// getters and setters
And update Thymeleaf template like this:
<form th:action="#{/products}" th:method="post" th:object="${formData}">
<input th:field="*{id}" type="number">
<button type="submit">Search</button>
</form>
Note that the value of th:object needs to match with the name used to add the SearchFormData instance to the model.
See Form handling with Thymeleaf for more info.
The following simple code will direct you to a URL that is generated from a concatenation of the base address of the <form>'s action attribute and the value of its first <input>:
document.querySelector("form").addEventListener("submit",function(ev){
ev.preventDefault();
this.action="/product/"+this.querySelector("input").value;
console.log(this.action);
// in real code: uncomment next line!
// this.submit()
})
<form>
Look up by id: <input type="text" value="123" />
</form>
In the real code you will delete the console.log() und uncomment the following line: this.submit().
Alternatively you could also do:
document.querySelector("form").addEventListener("submit",function(ev){
ev.preventDefault();
location = "/product/"+this.querySelector("input").value;
})
This will redirect you to the page without actually submitting the form.
I tried to find this in a lot of places, but it is not clearly written anywhere. For example in this documentation the usage is given only for JSP but not for JSF.
Example used in the documentation :
<textarea name="text">
<b><%= Encode.forHtmlContent(UNTRUSTED) %></b>
</textarea>
I need something similar for <h:outputText ... escape='true'> (escape attribute is not enough for Cross Site Scripting : Poor Validation).
Just use standard converter.
<h:outputText value="#{value}" escape="false">
<f:converter converterId="unsafeHTMLConverter" />
</h:outputText>
With some custom work like:
#FacesConverter("unsafeHTMLConverter")
public class UnsafeHTMLConverter implements Converter {
PolicyFactory policy = // your fancy policy
// (...)
#Override
public String getAsString(FacesContext context, UIComponent component, Object untrustedHTML) {
return policy.sanitize((String) untrustedHTML);
}
}
I am working with PrimeFaces messages, I want my whole page to scroll to top when p:messages is rendered.
Assign an ID to your p:message component
<p:messages autoUpdate="true" id="myMessage" />
Then, in your backing bean call RequestContext.scrollTo method:
in PrimeFaces >= 6.0:
PrimeFaces.current().scrollTo("myMessage")
in Primefaces < 6.0:
RequestContext context = RequestContext.getCurrentInstance();
context.scrollTo("myMessage");
which is deprecated in PrimeFaces 6.0
Deprecated with PrimeFaces < 6.2
In you backing bean (that one which produces the messages), you should know when you render a p:message. If so simply execute this:
RequestContext.getCurrentInstance().execute("window.scrollTo(0,0);");
Update:
With the newer PrimeFaces versions (>= 6.2), the approach to execute Javascript on the client side is (by using x and y coordinates):
PrimeFaces instance = PrimeFaces.current();
instance.execute("window.scrollTo(0,0);");
To scroll to an element use the element's clientId:
PrimeFaces instance = PrimeFaces.current();
instance.scrollTo("myElementsClientId");
Find more information here:
http://de.selfhtml.org/javascript/objekte/window.htm#scroll_to
examples with jQuery for smooth scrolling as well: Scroll to the top of the page using JavaScript/jQuery?
Lets say that your button is causing the messages to appear.
XHTML
<p:commandButton value="Save"
oncomplete="scrollToFirstMessage()" />
javascript
//javascript function which scroll to the first message in page
function scrollToFirstMessage() {
try {
PrimeFaces.scrollTo($('.ui-message :first-child').eq(0).parent().attr('id'));
} catch(err) {
//No Message was found!
}
}
Hope this helps.
There are valid answers already that show how to scroll to the p:messages component, but they all require you to execute code in a backing bean. This requires you to do / call the same in each action. None show how to scroll to the messages component when it is rendered (updated).
You can implement a phase listener and check messages are present and if the messages component's clientId is present in the PartialViewContext renderIds:
These client identifiers are used to identify components that will be processed during the render phase of the request processing lifecycle.
Your listener can look something like this:
public class MessagesUpdateListener implements PhaseListener {
private final String MESSAGES_ID = "yourMessagesClientId";
#Override
public void afterPhase(PhaseEvent event) {
// Empty
}
#Override
public void beforePhase(PhaseEvent event) {
FacesContext fc = FacesContext.getCurrentInstance();
if (!fc.getMessageList().isEmpty() &&
fc.getPartialViewContext().getRenderIds().contains(MESSAGES_ID)) {
RequestContext.getCurrentInstance().scrollTo(MESSAGES_ID);
}
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
}
Make sure to register it in your faces-config.xml:
<lifecycle>
<phase-listener>your.MessagesUpdateListener</phase-listener>
</lifecycle>
Tested with XHTML:
<h:form id="main">
<p:messages id="messages" />
<p:inputText id="text1" required="true" />
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
this<br/>is<br/>a<br/>long<br/>page<br/>this<br/>is<br/>a<br/>long<br/>page<br/>
<p:commandButton value="Update" update="messages text1"/>
<p:commandButton value="No update"/>
</h:form>
To check for global messages, use:
fc.getMessageList(null).isEmpty()
See also:
Add global message when field validation fails
im using GWT uibinder method and my html contains a textbox like
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:idmw="urn:import:com.testing.wid.impl">
<g:HTMLPanel>
<table align="center" valign="center" height="25%">
<tr><td><g:TextBox ui:field='searchS' /></td></tr>
</table>
</g:HTMLPanel>
How can i TURN OFF autocorrect and autocapitalize for this Textbox??
i tried
<g:TextBox ui:field='searchS' autocapitalize="off" autocorrect="off"/>
but i get
[ERROR] Class TextBox has no appropriate setAutocorrect()
method Element <g:TextBox autocapitalize='off' autocorrect='off' ui:field='searchS'>
Any other way i can do this???
Thanks
As already pointed by #Boris Brudnoy there is no built-in way to do it with TextBox. Takin futher his suggestion it will be nice to extract this into new custom component (to simplify reuse and support):
Add new package (for example com.app.shared.customcontrol)
Add new CustomTextBox:
public class CustomTextBox extends TextBox {
public void setAutocomplete(String value){
this.getElement().setAttribute("autocomplete", value);
}
public void setAutocapitalize(String value){
this.getElement().setAttribute("autocapitalize", value);
}
}
Declare new namespace using UI binder and use your component:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c="urn:import:com.app.shared.customcontrol">
<g:HTMLPanel ...>
<c:CustomTextBox ui:field="..." autocomplete="off" autocapitalize="off" />
</g:HTMLPanel>
</ui:UiBinder>
As alternative way if you want apply these settings system wide you can do it via constructor:
public class CustomTextBox extends TextBox {
public CustomTextBox() {
this.getElement().setAttribute("autocomplete", "off");
this.getElement().setAttribute("autocapitalize", "off");
}
....
}
What you've tried will not work since GWT doesn't translate UiBinder attributes directly into HTML element properties. Instead, as your error message hints, it looks up widget setter methods of the form set[UiBinder_attribute]. Since there is neither setAutocorrect nor setAutocapitalize method in the TextBox class, the errors you're getting are expected.
What you could do is drop to the element level and write something like this, e.g. in your widget's constructor:
public MyWidget() {
initWidget(uiBinder.createAndBindUi(this));
searchS.getElement().setProperty("autocapitalize", "off");
searchS.getElement().setProperty("autocorrect", "off");
}
I had to write a custom renderer for <h:commandLink/> tag to support data-* HTML5 attributes in order to use JSF 2.1 with jQuery mobile framework.
My JSF markup and the output generated by this markup are as follows:
<h:commandLink value="Prev" data-theme="e" data-role="button" data-inline="true" data-mini="true" data-icon="arrow-l"/>
<h:commandLink value="Page 1 of 3" data-theme="e" data-role="button" data-inline="true" data-mini="true"/>
<h:commandLink value="Next" data-theme="e" data-role="button" data-inline="true" data-mini="true" data-icon="arrow-r" data-iconpos="right"/>
It is obvious that my custom renderer properly renders the 2nd and the 3rd <h:commandLink/> tags, but not the 1st one. It seems the data-* attributes belong to the 1st tag is rendered with the immediate parent <div/> tag. This seems a strange (and buggy) behaviour of Mojarra (I use V 2.1.11). Please advice me how to overcome this?
My custom renderer code as follows:
public class MyCommandLinkRenderer extends CommandLinkRenderer {
#Override
public void encodeBegin(FacesContext context, UIComponent component) {
String[] attributes = {"data-theme", "data-role", "data-icon", "data-inline", "data-mini", "data-iconpos"};
ResponseWriter writer = context.getResponseWriter();
try {
for (String attribute : attributes) {
String value = (String) component.getAttributes().get(attribute);
if (value != null) {
writer.writeAttribute(attribute, value, attribute);
System.out.println(attribute + " " + value);
}
}
super.encodeBegin(context, component);
} catch (Exception e) {
}
}
}
You must call super.encodeBegin() before writing the attributes.
Otherwise you're writing the attributes to the previous HTML element, as confirmed by the generated HTML output. The super.encodeBegin() starts the new HTML element.
This is just a bug in your own code, not in Mojarra.
Update: also, overriding the encodeBegin() was not right in first place. You should rather be overriding the LinkRenderer#writeCommonLinkAttributes() method.
#Override
protected void writeCommonLinkAttributes(ResponseWriter writer, UIComponent component) throws IOException {
super.writeCommonLinkAttributes(writer, component);
// ...
}
It does by the way then not matter if you call super before or after your job.