JSF 1.2 DataTable
I know how to remove the row from datatable writing following code.
jsp
<h:graphicImage id="deleteRowBtn_img" url="../../images/table_icon_delete.gif" style="cursor:pointer" alt="Delete Row">
<a4j:support id="deleteRowBtn" event="onclick" actionListener="#{mnpAction.deleteMultiNoPortRow}" reRender="multiNoPortTable" oncomplete="resetViewConfigs();"/>
</h:graphicImage>
action bean
public void deleteMultiNoPortRow(ActionEvent ae) {
{
int index = abcBean.getDataTable().getRowIndex();
mnpBean.getMultiNoPortingList().remove(index);
}
}
But i want to know is there any other way to remove row from datatable in JSF1.2.
Any help regarding this appreciate!!!!!!
You can get the same appearance and functionality by using an a4j:commandButton and its image attribute instead of <h:graphicImage> as below.
<a4j:commandButton image="../../images/table_icon_delete.gif" actionListener="#{mnpAction.deleteMultiNoPortRow}"/>
If your <h:graphicImage> is in a column of the table, you can pass the var of the table to a method in your baking bean and remove that element from the list without having to use the row index. Here use action instead of actionListener.
<a4j:support id="deleteRowBtn" event="onclick" action="#{mnpAction.remove(myVar)}".../>
In mnpAction bean (Assuming the type of your list is T)
public void remove(T s) {
mnpBean.getMultiNoPortingList().remove(s);
}
Edit:
Since you are using JSF1.2 you may not use #{mnpAction.remove(myVar)}" to pass parameters to the bean if you don't like to upgrade your EL library.
Related
I have the following command button in the view with ID "save":
<p:panel style="border:none;text-align:left;margin:0;">
<p:commandButton value="Save Document" id="save" icon="fa fa-save"
disabled="#{dIGRCController.digrc.qconce == '020'}">
<f:param name="validate" value="true" />
</p:commandButton>
<p:commandButton value="Clear" icon="fa fa-undo"></p:commandButton>
</p:panel>
I am trying to dynamically assign a different actionListener. If the user wants to INSERT some new record, I want it to call the insert method. If the user wants to update an existing record, it should call the update method.
Right now I am trying to do this:
#PostConstruct
public void init() {
// setting the action listener of the Save Document button
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
// UIComponent button = viewRoot.findComponent("save");
CommandButton button = (CommandButton) viewRoot.findComponent("save");
FacesContext context = FacesContext.getCurrentInstance();
MethodExpression methodExpression = context
.getApplication()
.getExpressionFactory()
.createMethodExpression(context.getELContext(),
"#{dIGRCController.updateDocument}", null,
new Class[] { DIGRCController.class });
button.addActionListener(new MethodExpressionActionListener(
methodExpression));
}
I am getting a null pointer exception on the line:
button.addActionListener(new MethodExpressionActionListener(
methodExpression));
What am I doing wrong? Is there another way to accomplish what I am trying to do? I am using JSF 2.2, PrimeFaces 5.3 and OmniFaces 1.11.
The findComponent() takes a client ID as argument not a component ID. The client ID is exactly the value of the generated HTML id attribute associated with the component in question. In case of a command button, usually the component ID of the parent <h:form> is prepended, separated by the naming container separator character which defaults to :.
Given this,
<h:form id="form">
<p:commandButton id="save" ... />
</h:form>
the client ID would be form:save.
CommandButton button = (CommandButton) viewRoot.findComponent("form:save");
See also this related question as to identifying and using client ID: How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Unrelated to the concrete problem, manipulating the component tree in Java side is a poor practice. You'd better keep using XHTML+XML for this which is so much more self-documenting as to declaring/defining tree structures. You can use JSTL tags to dynamically build the view (note: this is different from dynamically rendering the view using rendered attribute!).
E.g.
<p:commandButton ... action="#{bean.save}">
<c:if test="#{bean.existing}">
<f:actionListener binding="#{bean.needsUpdate()}" />
</c:if>
</p:commandButton>
See also JSTL in JSF2 Facelets... makes sense?
Even more, you could just pass #{bean.existing} as method argument.
<p:commandButton ... action="#{bean.save(bean.existing)}" />
Both approaches are in turn admittedly kind of weird if #{bean.existing} refers the same bean as #{bean.save}. You could just check for that inside #{bean.save} itself.
public void save() {
if (existing) {
// UPDATE
} else {
// INSERT
}
}
Going further on that, this is IMO not the responsibility of frontend layer, but of the service layer. You pass the whole entity to the service layer which in turn checks based on PK if it's existing or not.
if (entity.getId() == null) {
// INSERT
} else {
// UPDATE
}
Prerequisites:
Glasfish 3.1
JSF 2.1
Primefaces 5.2
User Story:
I want to implement a delete row function on my Primefaces DataTable, the Delete Function has to be displayed within the table.
Implementation:
datatable header
<p:dataTable value="#{a.list}" var="var">
delete
<p:column headerText="Delete">
<p:commandLink value="-" action="#{a.delete(var)}" />
</p:column>
delete method in bean
public void delete(Something sth) {
model.getList().remove(sth);
}
Outcome:
When hovering over the commandLink its showing me this Uniform Resource Locator localhost/applicationname/#
Eclipse is giving me the Facelet Validator Warning Marker Syntax Error on this ExpressionLanguage Code #{a.delete(var)}
Question:
What am i missing in order to delete the row?
Solution:
I have changed to commandlink from JSF (not primefaces) and got the Error, that my method shouldnt be void, but String after changing that and returning null it works...
public String delete(Something sth) {
model.getList().remove(sth); return null;
}
I have a primefaces datatable and i have a column with filter.i would like to apply filter on the column from the backing bean.
I followed this example and i am able to get the input given filter text box into my bean.
but when i use setFilter ,the values are being set in the HashMap but filter is not being applied on the datatable.
Example column
<p:column filterBy="#{var.value}" headerText="Example" footerText="contains" filterMatchMode="contains" />
Bean is session scoped and the following code is in a function which gets called on a button click.
Map<String,String> theFilterValues = new HashMap<String,String>();
theFilterValues.put("filterColumn","someValue");
myDataTable.setFilters(theFilterValues);
this sets the values ,but there is no change on datatable.
i tried this but it did not help.
All i need is to set a filter on the datatable column upon a button click.
Thanks in advance
The values in the inputs of the DataTable filter are sent in the FacesContext request parameter map, and obtained by the DataTableRenderer when it is rendering the DataTable (see the encodeFilter method for PF 3.5, PF 4.0, or PF 6.1)
So, if your button is in the same form of the DataTable, the values of the filter are sent in the request parameter map, and the renderer will show those values over whatever else you want.
You'll need the button to be in a separate form:
<h:form>
<p:commandButton action="#{someBean.action()}" update="#([id$=dataTable])" />
</h:form>
<h:form>
<p:dataTable id="dataTable" [...] >
<p:column filterBy="#{var.col}" filterValue="#{someBean.filterValue}">
<h:outputText value="#{var.col}">
</p:column>
</p:dataTable>
</h:form>
And then, you can change the filterValue in the bean:
#Named
#SessionScoped
public SomeBean implements Serializable {
private String filterValue;
[...]
public void action() {
filterValue = "new value";
}
[getters/setters]
}
You can use a Map for the filterValues if you are using many filters.
As an alternative, if you need to redirect the user to a new page, you can put the values in the URL, instead of using filterValue. Example:
https://example.com/app/pageOfTheTable.xhtml?form:dataTable:colum:filter=new%20value
The part form:dataTable:colum:filter is the ID of the filter input. You can get that by inspecting the element using your browser. The principle is the same: you are using the request parameter map.
It may be useful to update the value of the backing bean when the user types something. I've found a patch here.
It basically changes populateFilterParameterMap method, in FilterFeature class, so it sets the value of the filterValue. You can put the added lines at the end of the for loop.
for ( ... ){
[...]
+ ValueExpression filterValueVE = column.getValueExpression("filterValue");
+ if (filterValueVE == null) {
+ ((UIComponent)column).getAttributes().put("filterValue", filterValue);
+ } else {
+ filterValueVE.setValue(context.getELContext(), filterValue);
+ }
}
I have read a lot of posts at Stackoverflow but I didn't succeed in implementing the belowmentioned problem from my side.
the problem is: I need to type some text in <p:inputTextarea> and when clicking on button I need to get this value in the bean method.
I.e.:
<p:inputTextarea binding="#{input}"/>
<p:commandButton action="#{pessoaMB.adicionarContato(input.value)}" immediate="true"/>
with the bean method:
public void adicionarContato(String value) {
System.out.println(value);
}
The code I'm using gives me a null value.
I'm using #ViewScoped and cannot change this.
First of all, a side note: it is a bad practice to work with JSF components, you should work with model instead. I.e. don't use binding="#{input}", but stick to value="#{bean.text}".
Second, I doubt that immediate="true" is used appropriately in your setup. When used in a UICommand component like <h:commandButton> it will cause to skip JSF lifecycle for components with immediate="false" (or omitted, as it's the default), thus their value won't be set at all. Still, JSF will still preset submittedValue behind the scenes before the action method is executed.
Also, I strongly recommend to read BalusC's blog post Debug JSF lifecycle, as it is more than enlightening on the topic.
As to the solution, I'd suggest to deal with value binding with the bean, as presented in the first comment. With this approach you won't need action method parameter at all. Moreover, rethink your use of immediate attribute. If you think it's correct then you've got two choices: (1) use immediate="true" on <p:inputTextarea> or (2) switch to action="#{bean.action(input.submittedValue)}".
I would've done this :
<h:form>
<p:inputText value="#{pessoaMB.input}"/>
<p:commandButton value="add" action="#{pessoaMB.adicionarContato}" />
</h:form>
input would be here a pessoaMB property with a getter and setter (an IDE can autogenerate it).
private String input;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
As for the adicionarContato method, it would be like this :
public void adicionarContato() {
System.out.println(input);
}
You should create a new class, i.e:
public class MyFields(){
String input1;
String input2; //and so on...
//getters and setters
}
Then, in pessoaMB create a property:
private MyFields inputFields; //getter and setter
Finally, in your xhtml file:
<h:form>
<p:inputText value="#{pessoaMB.inputFields.input1}"/>
<p:inputText value="#{pessoaMB.inputFields.input2}"/>
<!-- add more inputText components... -->
<p:commandButton value="add" action="#{pessoaMB.adicionarContato}" />
</h:form>
I have a managed bean under ViewScope. It has an instance variable inside it.
MetaData object has a inputItem object List.
#ManagedBean
#ViewScoped
public class ConBean implements Serializable {
private MetaData metadata;
#PostConstruct
#SuppressWarnings("unchecked")
public void init() throws IOException {
this.metadata = new MetaData ();
}
public void proc(){
List<InputItem> inputs= new ArrayList<InputItem>();
inputs.add(***** code to populate the inputItem List);
//after populating, inputs added to the metadata
metadata.setInputs(inputs);
}
//getters & setters
}
in my JSF , input list is populated inside a UI repeat.
<div id="inputplaceholder">
<ui:repeat value="#{conBean.metaData.inputs}" var="content">
</ui:repeat>
</div>
the div inputplaceholder is periodically updated using a richfaces poll.
<a4j:poll id="poll" interval="12000" action="#{conBean.proc}"
execute="#form" render="inputplaceholder"/>
The problem that I have is even though inputItems are set to the metaData object correctly inside the proc() method, when the view is rendered/partially updated, it doesn't get highlighted in the UI. so partial update takes no effect. I tried moving
this.metadata = new MetaData ();
inside the proc method but had no luck.
any ideas and help is highly appreciated.
thanks ...
Did the partial render really take place? This is impossible. There is namely no JSF component with the ID inputplaceholder. You assigned it to a plain HTML <div> element. Replace it by a fullworthy JSF component:
<h:panelGroup layout="block" id="inputplaceholder">
Also, since you used a relative ID in the render attribute, it will only scan for components in the same parent naming container component. The <ui:repeat> is such one, however the component with the desired ID is placed outside it. You'd like to use an absolute ID instead. Assuming that it's inside a <h:form> with a fixed ID:
<h:form id="myform">
<h:panelGroup layout="block" id="inputplaceholder">
...
then you should be referencing it in the render attribute as follows
render=":myform:inputplaceholder"