Reputation: 1539
Random Thought: I am hating this "lone wolf" behavior they coded into the dataScroller....
I am trying to implement a filter based on the user choice on a <p:selectOneMenu>
that would reload the contents shown in a <p:dataScroller>
from the ManagedBean based on the choice.
MB (EnglishNumberToWords) (random strings)
import java.util.*;
import se.answers.EnglishNumberToWords;
import java.security.SecureRandom;
@ManagedBean
@ViewScoped
public class bean {
private List<String> itens;
private Integer choice = 1; //initialize;
private LazyDataModel<String> model;
// getter setter
@PostConstruct
public void postConstruct() {
int count = loadStringsFromElsewhere();
model = new LazyModelImplmentation(this);
model.setRowCount(count);
}
public Map<String, Integer> mapChoices() {
Map<String, Integer> map = new LinkedHashMap<String, Integer>();
for(int ii=0;ii<5;ii++) {
map.put(ii, convertLessThanOneThousand(ii));
}
}
public List<String> getChunk(int first, int pageSize) {
SecureRandom random = new SecureRandom();
int listSize = itens.size();
int added = 0;
int end = int+pageSize;
while(end > itens.size(){
added++; //the real code here is different, I will just randomize.
int criteria = (random.nextInt(5) + 1);
if(criteria == choice) { // filters out Strings.
String ss = criteria + BigInteger(130, random).toString(32)
itens.add(ss);
}
}
return itens.subList(Math.min(first, itens.size()), Math.min(end, itens.size()));
}
/**
* Get the dataScroller itens from elsewhere, NOT a database.<p>
* here we will use only randons.
*/
private int loadStringsFromElsewhere() {
SecureRandom random = new SecureRandom();
if(itens == null) {
itens = new ArrayList<String>();
}
for(int ii=0;ii< (random.nextInt(50) + 100); ii++) {
int criteria = (random.nextInt(5) + 1);
String ss = criteria + BigInteger(130, random).toString(32);
itens.add(ss);
}
}
}
LazyModelImpl
import java.util.List;
import java.util.Map;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
public class LazyModelImplmentation extends LazyDataModel<String> {
private static final long serialVersionUID = 1L;
private Bean bean;
public LazyModelImplmentation(Bean bean) {
this.bean = bean;
}
@Override
public List<String> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, Object> filters) {
return bean.getChunk(first, pageSize);
}
}
JSF
<h:form prependId="false">
<p:selectOneMenu value="#{bean.choice}">
<f:selectItems value="#{bean.mapChoices()}" />
<p:ajax process="@form" update="@form" />
</p:selectOneMenu>
<p:dataScroller id="da_scroller" var="item"
value="#{bean.model}" rowIndexVar="index" chunkSize="10" lazy="true">
<!-- SHOW THE DATA IN THE item -->
<h:outputText value="#{index}: #{item.toString()}" />
<hr />
</p:dataScroller>
</h:form>
But the dataScroller just ignores the form update and keeps showing the same data. Only the new data loaded via the lazy model is updated, mixed with the old data.
How can I clean up the dataScroller on the form update so it displays only the new data (bonus points if it goes back to the first chunk).
Using Primefaces 5.0 on Tomcat 7 and jsf2.2 (but the jsf is on the tagging).
Upvotes: 3
Views: 1461
Reputation: 21
There is an easy way:
Just put the datascroller inside a panel, then:
= )
Upvotes: 0
Reputation: 1539
After fiddling around with the source for the <p:dataScroller>
I came up with no solution. There is no documented way to change what was already appended, and the component just appends more stuff.
So I had to hack my own solution:
Lie to the <p:dataScroller>
:
setRowCount()
on the lazyModel. It only fetches two chunks and then stop.Integer.MAX_VALUE
causes the dataScroller to halt (client-side) on the fetch of the second chunk. I suspect some Shlemiel the painter [1] [2] somewhere.Cheat: I have control of what is going to the dataScroller because I build the chunk on the @ManagedBean
, so If I want to reset the list and start serving from the beginning, I can. I will leave the exact implementation of the getChunk()
method (see the listing on the question, above) to the reader, but just keep your own count instead of relying on the params of LazyDataModel<T>.load()
.
<p:selectOneMenu>
(bind to the onstart, because you can't be sure to have a window to do it before the dataScroller updates itself:<p:selectOneMenu value="#{bean.choice}"> <f:selectItems value="#{bean.mapChoices()}" /> <p:ajax process="@form" update="@form" onstart="cleanScroller()" /> </p:selectOneMenu>
function cleanScroller() {
$('li.ui-datascroller-item').remove();
}
Upvotes: 3