2

I have a datatable in which each row has 24 hour input fields in it. At one point of time there are more than 1000 editable input fields. I noticed that while using p:cellEditor during ajax calls primefaces is submitting the entire datatable. How can I avoid that? Please find below the code that I have, and also find the comments on each important parts in them.

        <!-- Fires the cellEdit event to trigger the validations to happen as user tabs out of the input box -->
    <p:ajax event="cellEdit" listener="#{renderValidator.onCellEdit}"  update=":#{p:component('globalMessages')}" process="@this" /> 

    <p:column id="hour1" styleClass="col-right col-90">
        <f:facet name="header">
            <h:outputText value="1" escape="false"/>
        </f:facet>
        <p:cellEditor > 

            <f:facet name="output">
            <h:outputText value="#{row.amount[0]}" escape="false">
            <f:convertNumber  maxFractionDigits="3" minFractionDigits="3" maxIntegerDigits="5" />
            </h:outputText>
            </f:facet> 
            <f:facet name="input">
            <p:inputText id="hour1Input" value="#{row.amount[0]}" maxlength="10" size="10"  readonly="#{row.readOnly}" onchange='PowerMeter.setPowerMeterChange()'
            styleClass="col-right" valueChangeListener="#{row.setDirtyFlag(true)}"  >
            <!-- formats data the way its displayed -->
            <f:convertNumber  maxFractionDigits="3" minFractionDigits="3" maxIntegerDigits="5" />
            <!-- validates the input value w.r.t a custom validator -->
            <f:validator validatorId="hourlyValueValidator" for="hour1Input" /> 
            <!-- javascript restricting user to input alpha numeric characters -->
            <pe:keyFilter testFunction="return PowerMeter.isValidMWH(this, c);" />
            </p:inputText>
            </f:facet>          
        </p:cellEditor>
    </p:column> 
Sabarish
  • 862
  • 1
  • 14
  • 23
  • Durng Ajax calls for validation, I would prefer just that particular input text to be passed. I tried replacing @this with the id 'hour1Input' but still in chrome I could see that whole table is getting submitted. – Sabarish Apr 24 '13 at 21:25
  • What about trying [lazy load](http://www.primefaces.org/showcase/ui/datatableLazy.jsf)? Or instead celleditor you can implement your own button. That one is not an easy job. – Ömer Faruk Almalı Apr 24 '13 at 21:27

2 Answers2

2

On Ajax requests, JSF sends the data for all input components in the form by default. Even if only one out of 100 components is executed in the partial lifecycle. With PrimeFaces you can alter this behavior by setting partialSubmit to true like this:

<p:ajax partialSubmit="true" event="cellEdit" process="@this"
    listener="#{renderValidator.onCellEdit}"
    update=":#{p:component('globalMessages')}"/> 
Michi
  • 1,595
  • 10
  • 11
  • Tried that @Michi still it submits the entire input fields. I have to limit this behaviour as its throwing an illegal state exception 'More than the maximum number of request parameters (GET plus POST) for a single request ([512]) were detected'. Although I know a work around for this, I prefer to handle it at ajax level and not let Ajax pass all untouched variables. – Sabarish Apr 25 '13 at 13:38
  • Which version of PrimeFaces do you use? I don't know when the partial submit feature was added. – Michi Apr 26 '13 at 09:20
0

Primefaces uses the PrimeFaces.ajax.AjaxUtils.send function to build Ajax requests. To determine what data need to be send to the server it uses jQuery find function and then serializeArray which is used to build a POST requests.

componentPostParams = jqProcess.find(':input').serializeArray();

Unfortunately when the liveScroll attribute is enabled for the <p:DataTable> and there is already a huge amount of data fetched it will process all input controls no matter if <p:cellEditor> have only one input facet visible.

Data table with only one input element visible

To change this functionality I overrode PrimeFaces.ajax.AjaxUtils.send function in the below form

var pFacesSend = PrimeFaces.ajax.AjaxUtils.send;
PrimeFaces.ajax.AjaxUtils.send = function(cfg) {
    if (myCase) {
        // Custom send
    } else {
        pFacesSend(cfg);
    }
};

And in myCase I changed additionally serialization from this:

componentPostParams = jqProcess.find(':input').serializeArray();

Into this:

if (!customSerializationCondition) {
    componentPostParams = jqProcess.find(':input').serializeArray();
} else {
    componentPostParams = jqProcess.find(':input').filter(function() {
        return $(this).parent().css('display') !== 'none';
    }).serializeArray();
}

This solution builds a POST request that only includes visible input fields and because of my editMode set to cell I have only one <input> visible. It works for Primefaces v4.0 and should work whenever the input parent tag uses css display attribute to hide input facet in the editor.

Addison
  • 7,322
  • 2
  • 39
  • 55
Michał
  • 56
  • 2