Can I add JSF components dynamically? I need to have a form with a button which should add one <h:inputText> to the form. Is this possible?
I know this should be possible in JavaScript somehow. Do anybody know how to do this in JSF? I think the major problem is how do I get or set values of new inputs via #{value}.
Use an iterating component like <h:dataTable> or <ui:repeat> to display a dynamically sized List of entities. Make the bean #ViewScoped to ensure that the list is remembered across postbacks on the same view instead of recreated over and over.
Kickoff example with <h:dataTable> (when using <ui:repeat> simply replace <h:dataTable> by <ui:repeat>, and <h:column> by e.g. <li> or <div>):
<h:form>
<h:dataTable value="#{bean.items}" var="item">
<h:column><h:inputText value="#{item.value}" /></h:column>
<h:column><h:commandButton value="remove" action="#{bean.remove(item)}" /></h:column>
</h:dataTable>
<h:commandButton value="add" action="#{bean.add}" />
<h:commandButton value="save" action="#{bean.save}" />
</h:form>
Managed bean:
#Named
#ViewScoped
public class Bean {
private List<Item> items;
#PostConstruct
public void init() {
items = new ArrayList<>();
}
public void add() {
items.add(new Item());
}
public void remove(Item item) {
items.remove(item);
}
public void save() {
System.out.println("items: " + items);
}
public List<Item> getItems() {
return items;
}
}
Model:
public class Item {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String toString() {
return String.format("Item[value=%s]", value);
}
}
See also:
Recommended JSF 2.0 CRUD frameworks
How to create dynamic JSF form fields
How to implement a dynamic list with a JSF 2.0 Composite Component?
How to choose the right bean scope?
It's should be like that
Bind a form tag to the bean property
<form binding="#{myBean.myform}">...</form>
#ManagedBean("myBean")
public class Bean{
property HtmlForm myform;
}
on event, create a new instance of the input component
HtmlInputText input=new HtmlInputText();
and attach to the your form
myform.getChildren().add(input);
Use h:dataTable to add elements dynamically... Have a list of any type you want to provide values for dataTable...
In h:dataTable... you can include the element tag to create inside <h:column>
It will be used to generate elements you want to create dynamically.
Related
I've got a web page with a form in it, which includes a linked image, which whenever clicked, it will request the graphicBean, as well as the execution of the action graficarTorta (action of the CommandLink) and once the function has been generated, it must update the label with the id: graficaGenerada (update of the CommandLink).
At the end of the page you can find the PanelGroup label which contains the graficaGenerada id, that is to say, whenever the whole graficarTorta function has executed, the update label is the one from PanelGroup, which title is Gráfica resultante.
In the bean, the variables model and example are new PieChartModel() and "ONE" respectively. When the function is executed, the variable model turns into a graph of specific data and example turns into "TWO".
Problem is that visually turns into a "TWO", but doesn't show anything. I'm sure the only problem has to do with renderization or some visual component, because once I refresh the page, the chart is displayed with the updated data.
How can I make the chart show the updates without refreshing the whole page?
This is my code:
graficas.xhtml
<h:form>
<h:panelGroup id="pG_descripcionFormulario">
<p:commandLink update = ":graficaGenerada" process="#this" action="#{graphicBean.graficarTorta}">
<b:image value = "../resources/imgs/torta.jpg" style = "width:200px;height: 200px" class = "img-circle efectoZoom"/>
<f:ajax execute="pG_descripcionFormulario" render="pG_descripcionFormulario" />
</p:commandLink>
</h:panelGroup>
</h:form>
...
<h:panelGroup id = "graficaGenerada">
<h1>Gráfica resultante</h1>
<h:outputText value = "#{graphicBean.example}"/>
<p:chart type = "pie" model="#{graphicBean.model}" />
</h:panelGroup>
GraphicBean.java
import java.io.IOException;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import model.entities.Formulario;
import org.primefaces.model.chart.PieChartModel;
#ManagedBean
#SessionScoped
public class GraphicBean {
private PieChartModel model;
private String example = "ONE";
public GraphicBean() {
model = new PieChartModel();
}
public String graficarTorta() {
example = "DOS";
model = new PieChartModel();
model.set("A",1);
model.set("B",2);
model.set("C",3);
model.setTitle("Gráfica de torta");
model.setLegendPosition("w");
return "grafica";
}
public PieChartModel getModel() {
return model;
}
public void setModel(PieChartModel model) {
this.model = model;
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
}
Thanks a lot for your help!
My View uses the Model like below:
public class ObjectViewModel
{
public int ChosenVariant{ get; set; }
public List<Object> Objects{ get; set; }
}
but on page I am displaying details only of one of Object from the list (whose id is equal ChosenVariant).
On the same page I have radio buttons and each of them is binded to one of the Objects from the list:
#foreach (var obj in Model.Objects)
{
<div class="radio">
#{
var options = new RouteValueDictionary();
options["onchange"] = "UpdatePage()";
if (product.ID == Model.ChosenVariant)
{
options["checked"] = "checked";
}
}
#Html.RadioButtonFor(p => Model.ChosenVariant, #product.ID, options)
</div>
}
My problem is that how I can refresh the Model.ChosenVariant and render once again page without refresh?
My first idea was returning whole Model with new value of Model.ChosenVariant in javascript function (on onchange radio button).
This function will call Post action to a Controler, which return once again whole Model (but with new changed Model.ChosenVariant. Then on done action of this Post call I will use $(panel).html(data); for refresh the page.
Is there any easier way to change the current viewmodel without calling Controller?
Can I add JSF components dynamically? I need to have a form with a button which should add one <h:inputText> to the form. Is this possible?
I know this should be possible in JavaScript somehow. Do anybody know how to do this in JSF? I think the major problem is how do I get or set values of new inputs via #{value}.
Use an iterating component like <h:dataTable> or <ui:repeat> to display a dynamically sized List of entities. Make the bean #ViewScoped to ensure that the list is remembered across postbacks on the same view instead of recreated over and over.
Kickoff example with <h:dataTable> (when using <ui:repeat> simply replace <h:dataTable> by <ui:repeat>, and <h:column> by e.g. <li> or <div>):
<h:form>
<h:dataTable value="#{bean.items}" var="item">
<h:column><h:inputText value="#{item.value}" /></h:column>
<h:column><h:commandButton value="remove" action="#{bean.remove(item)}" /></h:column>
</h:dataTable>
<h:commandButton value="add" action="#{bean.add}" />
<h:commandButton value="save" action="#{bean.save}" />
</h:form>
Managed bean:
#Named
#ViewScoped
public class Bean {
private List<Item> items;
#PostConstruct
public void init() {
items = new ArrayList<>();
}
public void add() {
items.add(new Item());
}
public void remove(Item item) {
items.remove(item);
}
public void save() {
System.out.println("items: " + items);
}
public List<Item> getItems() {
return items;
}
}
Model:
public class Item {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String toString() {
return String.format("Item[value=%s]", value);
}
}
See also:
Recommended JSF 2.0 CRUD frameworks
How to create dynamic JSF form fields
How to implement a dynamic list with a JSF 2.0 Composite Component?
How to choose the right bean scope?
It's should be like that
Bind a form tag to the bean property
<form binding="#{myBean.myform}">...</form>
#ManagedBean("myBean")
public class Bean{
property HtmlForm myform;
}
on event, create a new instance of the input component
HtmlInputText input=new HtmlInputText();
and attach to the your form
myform.getChildren().add(input);
Use h:dataTable to add elements dynamically... Have a list of any type you want to provide values for dataTable...
In h:dataTable... you can include the element tag to create inside <h:column>
It will be used to generate elements you want to create dynamically.
Is there a way to send some JS value to my bean, using the ActionListener property of a p:commandButton?
Example:
<p:inputText id="txtColaborador1"></p:inputText>
<p:commandButton ajax="true" actionListener="#{demandaController.validarLogin(document.getElementById('form\:j_idt100\:txtColaborador1').value)}""></p:commandButton>
And in my Bean:
....
public class DemandaController
public void validarLogin(String text1) {
//....
}
}
Also, would be better using widgetVar.
I'm already providing another solution for this case, cause i can recover that text value in my bean....but still, is there way to do that?
You can achieve this by using Primefaces Remote Command
remoteCommand
<p:remoteCommand name="validarLoginCommand"
actionListener="#{demandaController.validarLogin()}"/>
Button
<p:inputText id="txtColaborador1" widgetVar="txtColaboradorVar"></p:inputText>
<p:commandButton onclick="handleLogin()"></p:commandButton>
JS
function handleLogin() {
myJSValue = txtColaboradorVar.jq.val();
validarLoginCommand([{name: 'myJSValue', value: myJSValue}]);
}
Managed Bean
public void validarLogin() {
FacesContext context = FacesContext.getCurrentInstance();
Map map = context.getExternalContext().getRequestParameterMap();
myJSValue = (String) map.get("myJSValue");
}
Hope this Helps.
I'm using a RichFaces commandbutton and I need it to execute two functions on click, one after the other. Right now, I have the code like so:
<a4j:commandButton styleClass="btn-hide"
onl
id="btnId"
type="submit"
value="addNew"
rendered="true"
reRender="panel"
eventsQueue="eventQueue"
status="eventQueue"
actionListener="#{(someMethod.something)}"
oncomplete="javascript:something;this.disabled=false"
onclick="Bean.setDesc(document.getElementById('inputArea').value);this.disable=false"
ignoreDupResponses="true"
immediate= "true">
<s:conversationId></s:conversationId>
</a4j:commandButton>
If you look at the onclick portion, I need the Bean.setDesc to run first and then this.disabled=false. How would I go about doing this chronologically?
Thanks
Here's a code stub to get you started. You'll want to use a4j:jsFunction if you are looking to grab values directly from the client and pass them to a server method with javascript.
<h:form id="form1" prependId="false">
<a4j:jsFunction
name="setDesc"
action="#{exampleBean.actionMethod()}"
immediate="true">
<a4j:param name="inputAreaValue" assignTo="#{exampleBean.desc}"/>
</a4j:jsFunction>
<h:commandButton id="button" onclick="setDesc(document.getElementById('inputArea').value); this.disabled = true;" />
</h:form>
and the managed bean:
#ManagedBean(name = "exampleBean")
#SessionScoped
public class ExampleBean implements Serializable {
private static final long serialVersionUID = 6823632613070575039L;
private String desc;
public String getDesc() { return desc; }
public void setDesc(String desc) { this.desc = desc; }
/**
* Action Method
*/
public void actionMethod() {
// do something here
}
}