Monday, April 6, 2020

Filtering ADF dynamic table with array list using Lambda Expression(Java 8 or Higher)

We may need to programmatically fill data that may comes from a service inside an array list, to view this list we can bind it to an ADF table component.

But can we filter this list in the JSF view ?

Lets' see an example:

1- We have a Java class called "Car" and defined as:
public class Car {
    int modelNo;
    String name;
    public Car(int x , String y) {
         modelNo = x;
         name = y;
     }
    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }
    public int getModelNo() {
        return modelNo;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
2- We have another class "Cars" contains list of cars, data generated at java class level as :
import java.util.ArrayList;
import java.util.List;
public class Cars {
    public List<Car> getCarsAsList(){
        List<Car> cars = new ArrayList();
        Car car = new Car(1,"Avalon");
        Car car2 = new Car(1,"Camry");
        Car car3 = new Car(2,"Hyndai");
        cars.add(car);
        cars.add(car2);
        cars.add(car3);
        return cars ;
    }
}
 To display previous list of cars, we will create a JSF page and assign the list to the value of the table :
<af:form id="f1">
    <af:table var="row" rowBandingInterval="0" id="t1"
              value="#{backingBeanScope.cars.carsAsList}"
              partialTriggers="::it1">
        <af:column sortable="false" headerText="CountryName" id="c1" rowHeader="true">
            <af:outputText value="#{row.modelNo}" id="ot1" partialTriggers="::it1"/>
        </af:column>
        <af:column sortable="false" headerText="Currency" id="c2">
            <af:outputText value="#{row.name}" id="ot2"  partialTriggers="::it1"/>
        </af:column>
    </af:table>
</af:form>

Now, We need to filter the table when a search input text is filled otherwise retrieve the list as it is.

1- Create a search input text ,with value  "#{pageFlowScope.modelNo}".
2- Set the search input text "autoSubmit" property  to  "true" and set the table partial trigger to that input text.
3-

a - when the search input text is empty, value of the table should be the list as it is without filtering:
value = "#{backingBeanScope.cars.carsAsList}"

b- when the search input text is filled, we will need to filter the list, ,so we will use lambda expression to filter the table when the search text field is filled as :
value = "#{backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo)}"
Combining a and b conditions we can form it as if-else expression language as:

value="#{pageFlowScope.modelNo !='' ? backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo).toList() : backingBeanScope.cars.carsAsList}"
value="#{pageFlowScope.modelNo !='' ? backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo).toList() : backingBeanScope.cars.carsAsList}"
af:form id="f1">
    <af:inputText id="it1" value="#{pageFlowScope.modelNo}" label="Search Model Number" autoSubmit="true"/>
    <af:table var="row" rowBandingInterval="0" id="t1"
              value="#{pageFlowScope.modelNo !=null and pageFlowScope.modelNo !=''? backingBeanScope.cars.carsAsList.stream().filter(car->car.modelNo == pageFlowScope.modelNo).toList() : backingBeanScope.cars.carsAsList}"
              partialTriggers="::it1">
        <af:column sortable="false" headerText="Model Number" id="c1" rowHeader="true">
            <af:outputText value="#{row.modelNo}" id="ot1" partialTriggers="::it1"/>
        </af:column>
        <af:column sortable="false" headerText="Car Name" id="c2">
            <af:outputText value="#{row.name}" id="ot2"  partialTriggers="::it1"/>
        </af:column>
    </af:table>
</af:form>

To convert "Car Name" field to upper case
 <af:table var="row" rowBandingInterval="0" id="t1"

                      value="#{backingBeanScope.cars.carsAsList.stream().map((car)->[car.modelNo,car.name.toUpperCase()]).toList()}"

                      partialTriggers="::it1">

                <af:column sortable="false" headerText="CountryName" id="c1" rowHeader="true">

                    <af:outputText value="#{row[0]}" id="ot1"/>

                </af:column>

                <af:column sortable="false" headerText="Currency" id="c2">

                    <af:outputText value="#{row[1]}" id="ot2"/>

                </af:column>

            </af:table>

No comments:

Post a Comment

java - fill distinct objects in ArrayList

If you have a list that contains some objects that it is considered as duplication when two or three fields of these objects are equal. How ...