openui5: Data binding not supported for sap.ui.model.Filter value1/value2 properties

UI5 Version 1.22.3 (built at , last change) User Agent Chrome/36.0.1985.143

Reproducable example: http://jsbin.com/nehato/2/edit?js,output

See also: http://stackoverflow.com/questions/25387580/not-possible-to-set-filter-value-using-data-binding

Steps to reproduce:

If I use a filter where the filter value value1 is specified by data binding:

new sap.ui.model.Filter({
    path     : "division", 
    operator : sap.ui.model.FilterOperator.EQ, 
    value1   : "{/someProperty}"
})

then the dropdown does not render any items

However, if I hardcode a value at property value1:

new sap.ui.model.Filter({
    path     : "division", 
    operator : sap.ui.model.FilterOperator.EQ, 
    value1   : "Test"
})

then the filter works as expected.

Possible root-cause:

As Allen Zhang discovered in the aforementioned Stackoverflow topic, the Filter’s properties oValue1 and oValue2 do not parse any data binding path:

/**
 * Provides a JS filter function for the given filter
 * @name sap.ui.model.ClientListBinding#getFilterFunction
 * @function
 */
ClientListBinding.prototype.getFilterFunction = function(oFilter){
    if (oFilter.fnTest) {
        return oFilter.fnTest;
    }
    var oValue1 = this.normalizeFilterValue(oFilter.oValue1),
        oValue2 = this.normalizeFilterValue(oFilter.oValue2);
    //etc...

(Source code here: https://openui5.hana.ondemand.com/resources/sap/ui/model/ClientListBinding-dbg.js)

Reasoning why it should work with databinding

Imagine you have a table, and one of the columns shows a dropdown box for each entry in the table. The entries in the dropdown box have to be filtered based on a value in the current table row (for instance, each row in the table has a client field, and the dropdown should only list the projects for that corresponding client: screen shot 2014-08-20 at 08 53 33

In code:

oTable.addColumn(new sap.ui.table.Column({
    label: new sap.ui.commons.Label({
        text: "Projects"
    }),
    template: new sap.ui.commons.DropdownBox({
        selectedKey: "{tablemodel>project}",
        items: {
            path: "metadatamodel>/allprojects",
            template: new sap.ui.core.ListItem({
                text: "{metadatamodel>projectDescription}",
                key: "{metadatamodel>projectKey}"
            }),
            filters: [new sap.ui.model.Filter("projectClient", sap.ui.model.FilterOperator.EQ, "{tablemodel>client}")]
        }
    })
}))

Explanation

  1. The table records contain, among others, a field client and project
  2. The dropdown template control in the table column is bound to a property allprojects which contains an array of objects {projectKey : "zzz", projectDescription : "zzz", projectClient : "someClient"}
  3. The dropdown template has a filter, which filters the dropdown’s model property projectClient based on the corresponding table model array item’s property client

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Reactions: 7
  • Comments: 25 (5 by maintainers)

Most upvoted comments

@rikusv @qualiture It’s been quite a while that this feature request had been brought up. Thanks for all your input and we apologize for the delays. Now we started to review the topic with our binding experts, again. Unfortunately, we don’t see to address it properly and suggest to keep using more explicit coding, typically in the controller.

Some reasons why we no longer consider an implementation (even that we had plans to do so back then): In order to benefit from the existing data binding capabilities one would turn the rather simple Filter objects into ManagedObjects (instead of reimplementing relevant parts in a redundant way). Only the comprehensive feature set of ManagedObject would allow to address reasonably powerful binding expressions in a dynamic filter. Just to use limited binding features wouldn’t cover some expected, real-life scenarios, e.g. referring to another model within the binding expression. Thus, one would need to have full lifecycle support for model creation, binding updates, etc. How and when to process different binding updates isn’t straightforward. Such implicit behavior could trigger some awkward update effects in (non-trivial) apps.

Therefore, in many real app scenarios we still advise to keep having more control about (re-)applying an updated filter or a set of filters, respectively. We suggest to go for the typical coding, albeit less elegant than the proposed dynamic filter declaration. As an example along those lines:

  • if model isn’t available yet, attach to modelContextChange event in control
  • use bindProperty() to create bindings for the filter values
  • attach to change event of those bindings
  • in handler (re-)create filter objects with those values
  • (re-)apply those filter objects on the binding to be filtered

Hope that helps, and the more explicit coding also comes with some benefits (such as more control and less implicit update flows).

Is there any feature update yet? Or a “workaround” for this?

Is there any upate on that ? Would make it a lot easier when using filters in XML View.

Is there currently any working work around to achieve dynamic filters and XML Views ?

@Michadelic @qualiture I’ve implemented a quick solution for this, more as a way for me to start getting the hang of working in UI5 libraries than anything else. I’m happy to continue working on it if there is some supportive feedback. The changes are in this branch and include the following:

  • Additions to the updateBindings method of sap.ui.base.ManagedObject.
  • A sample, sap.m.sample.ListFilterBinding, that can be accessed in the Explored app samples for sap.m.List (name: “List - Dynamic Filter Binding in View”).

In short, this is how it works:

  • value1 is checked to see if it is wrapped in “{}” - if so, a binding must be processed.
  • value1 is parsed and the resulting binding info (model and path) stored as a property of the filter.
  • If the model is available, the binding info is used to create a binding and it is also stored as a property of the filter; if the model is not yet available, the managed object’s modelContextChange event is used to try again later.
  • Once the binding is stored in the filter, the value is fetched and the filter applied.

(As a first stab I’ve just done value1, not value2).

This means the sap.m.List items aggregation can be set like this

items="{
			path: '/ProductCollection',
			filters: [
				{path: 'Category', operator: 'EQ', value1: '{ViewControl>/Category}'}
			]
		}"

and the filter will be reprocessed when ViewControl>/Category is changed.

In the sample I’ve used sap.m.Select in the list toolbar like this

<Select
						forceSelection="false"
						selectedKey="{ViewControl>/Category}"
						items="{/ProductCollectionStats/Filters/0/values}">
						<core:Item key="{text}" text="{text}"/>
					</Select>

This is working for me with both JSON and OData list bindings, but I haven’t done a lot of testing.

I’m not very familiar with the inner workings of the UI5 libraries, so I might very well have missed many important considerations​ - any feedback is welcome!

Two things that “feel” potentially incorrect, is:

  • all the code is directly in ManagedObject.prototype.updateBindings, whereas there may be more suitable classes and methods to use.
  • additional​ properties (binding info and binding) are added to Filter, but no methods (getters, setters, etc.) to work with these are implemented.

Also for me this is a bigger open issue with only ‘not so nice’ workarounds. Is it possible to prioritize this request?

it’s already halfway into 2023, and surprisingly this is still not supported. can anyone else help to confirm? thanks

Hello @Michadelic @qualiture

We have a similar requirement. is this feature now supported in SAPUI5 XML views with data-binding? Please advice.

I am in UI5 training right now, and when we got to the filter slides, this was the first thing I thought of and immediately Google’d to see if it were possible. I agree this is an important feature.

Hello guys, the feature is now on the product backlog of SAPUI5. We will definitely implement it but we do not have a concrete timeline yet. I marked this as “contributions welcome”, you are invited to create a pull request and add the feature if you want to speed up this request.

If you would like to contribute, please contact us for further details, the implementation needs to consider internal details and special cases for two way binding in UI5.

Cheers,

Michael