question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Datatable filtering in non-lazy datatables triggers undesirable valueChangeEvent when no records are found

See original GitHub issue

Defect Whenever a non-lazy datatable is filtered so that the filtered result list is empty, i.e., no records are found, and afterwards the filter is cleared so that the filtered result list is not empty anymore, valueChangeEvents are triggered. In our project, we use the same approach for lazy datatables and everything works as expected.

Environment:

  • PF Version: 11.0.0-SNAPSHOT
  • JSF + version: Mojarra 2.2.20 (default Mojarra used in the PF reproducer)
  • Affected browsers: All

Reproducer Steps to reproduce the behavior:

  1. Go to the test view.
  2. Select either one of the entries in the datatable via the checkbox.
  3. Filter the table for a non-existing id, e.g., 4.
  4. Clear the filter.
  5. All the checkbox values are false, i.e., the model was changed as the valueChangeEvent was triggered.

Expected behavior The valueChangeListener should only be called once when the respective entry is selected. Log:

// select
VALUE CHANGED
OLD value: null
NEW value: true

Actual behavior The valueChangeListener is called three times instead of only once: Log:

// select
VALUE CHANGED
OLD value: null
NEW value: true
// filter id by '4'
VALUE CHANGED
OLD value: null
NEW value: false
// clear the filter
VALUE CHANGED
OLD value: true
NEW value: false

test.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

<h:head>
  <title>PrimeFaces Test</title>
  <h:outputScript name="test.js" />
</h:head>
<h:body>
  <h1>Datatable filter triggers valueChange event</h1>
  <h:form id="edit">
    <p:dataTable
      var="entity"
      value="#{testView.entities}"
      id="entitiesTable">
      <p:column
        exportable="false"
        headerText="Select">
        <h:selectBooleanCheckbox
          id="checkbox"
          value="#{testView.markedSamplesMap[entity]}"
          valueChangeListener="#{testView.valueChangeListener}">
          <p:ajax
            event="change"
            global="false" />
        </h:selectBooleanCheckbox>
      </p:column>
      <p:column
        exportable="false"
        field="id"
        headerText="Id"
        filterMatchMode="contains" />
      <p:column
        exportable="false"
        field="name"
        headerText="Name"
        filterMatchMode="contains" />
    </p:dataTable>
  </h:form>
</h:body>
</html>

TestView.java

package org.primefaces.test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.event.ValueChangeEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class TestView implements Serializable {

    private List<Sample> entities;

    private Map<Sample, Boolean> markedSamplesMap = new HashMap<>();

    /**
     * Get entities.
     *
     * @return the entities
     */
    public List<Sample> getEntities() {
        return entities;
    }

    /**
     * Get markedSamplesMap.
     *
     * @return the markedSamplesMap
     */
    public Map<Sample, Boolean> getMarkedSamplesMap() {
        return markedSamplesMap;
    }

    @PostConstruct
    public void init() {
        entities = new ArrayList<>();
        entities.add(new Sample(1, "first"));
        entities.add(new Sample(2, "second"));
    }

    /**
     * Set entities.
     *
     * @param entities the entities to set
     */
    public void setEntities(List<Sample> entities) {
        this.entities = entities;
    }

    /**
     * Set markedSamplesMap.
     *
     * @param markedSamplesMap the markedSamplesMap to set
     */
    public void setMarkedSamplesMap(Map<Sample, Boolean> markedSamplesMap) {
        this.markedSamplesMap = markedSamplesMap;
    }

    public void valueChangeListener(ValueChangeEvent event) {
        System.out.println("VALUE CHANGED");
        System.out.println("OLD value: " + event.getOldValue());
        System.out.println("NEW value: " + event.getNewValue());
    }
}

Sample.java

package org.primefaces.test;

import java.io.Serializable;

public class Sample implements Serializable {

    private static final long serialVersionUID = 1L;

    private long id;

    private String name;

    public Sample(long id, String name) {
        this.id = id;
        this.name = name;
    }

    /**
     * Get id.
     *
     * @return the id
     */
    public long getId() {
        return id;
    }

    /**
     * Get name.
     *
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * Set id.
     *
     * @param id the id to set
     */
    public void setId(long id) {
        this.id = id;
    }

    /**
     * Set name.
     *
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
}

pf-issue-7223.zip

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mellowarecommented, Apr 13, 2021

Nope you will have to wait for Mojarra 2.3.15, 3.0.1 or 4.0 which is when that fix is going in.

0reactions
MatthiasScherrerFGCZcommented, Apr 13, 2021

You can verify its the same issue if you run your reproducer with mvn clean jetty:run -Pmyfaces23 and try it. if it works then its definitely the same Mojarra bug.

I tested it and as you said, it works fine with MyFaces. It still does call the valueChangeListener twice instead of only once, however the values are not changed as desired. Is there currently a workaround since it is not a PF issue?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Datatable: SelectOneMenu has wrong value after filtering #7026
Datatable filtering in non-lazy datatables triggers undesirable valueChangeEvent when no records are found #7223.
Read more >
nasty behavior (bugs?) on search events triggered from ...
Although this is sub-optimal, it isn't quite as bad as it looks initially - DataTables' filtering code will see that there is no...
Read more >
When a datatable (jquery) has data after getting filtered, make ...
I have a DataTable (jQuery) that currently allows me to filter my data when I enter a string inside an input field. By...
Read more >
USER GUIDE 5.1 - PrimeFaces
CellEditor is a helper component of datatable used for incell editing. Info. Tag. cellEditor. Component Class org.primefaces.component.celleditor.CellEditor.
Read more >
jQuery DataTables: Why click event handler does not work
Provides solution to a problem when click and other event handlers don't work on pages other than first or when table is sorted...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found