I'm trying to use RadListView with client side binding, everything works well, including the filters, bu they are always concatenated as ANDs and I need some of them to be ORs, so I'm trying to use the builder() featured in this article:
http://www.telerik.com/blogs/client-side-databinding-with-radlistview-for-asp-net-ajax---part-3#filtering
Here's an example of the JSON source this is filtering:
[{"OpportunityId":1,"OpportunityTitle":"\r\nMainframe Programmer for Giftware, Jewellery & Tableware","OpportunityType":"Realocation","ClientImageUrl":"/Client/Images/intel.jpg","ClientName":"Intel","PublishDate":"2016-04-27T00:00:00","PublishDaysSince2000":5961,"ExpiryDaysSince2000":6046,"CountryName":"Portugal","CityName":"Braga","SkillsList":[11,12,13],"Skills":"-11-12-13-","Salary":15000,"ContractTypeId":6,"ScheduleTypeId":2,"CityId":9,"ClientId":7,"ExperienceLevelId":null,"AcademicLevelId":3,"Reference":"AI5MU5PK3CWD","RequestDateDays":5961,"OpportunityStateId":4,"ManagerId":123,"RecruiterId":123,"CategoryId":20},{"OpportunityId":2,"OpportunityTitle":"Microprocessor Researcher","OpportunityType":"Project","ClientImageUrl":"/Client/Images/intel.jpg","ClientName":"Intel","PublishDate":"2016-04-27T00:00:00","PublishDaysSince2000":5961,"ExpiryDaysSince2000":6046,"CountryName":"Portugal","CityName":"Algarve","SkillsList":[11],"Skills":"-11-","Salary":15000,"ContractTypeId":4,"ScheduleTypeId":2,"CityId":10,"ClientId":7,"ExperienceLevelId":null,"AcademicLevelId":3,"Reference":"6PPH62GCRGWP","RequestDateDays":5961,"OpportunityStateId":3,"ManagerId":123,"RecruiterId":123,"CategoryId":21}
...
if I use the add: filterExpressions.add("OpportunityId", Telerik.Web.UI.RadListViewFilterFunction.Contains, 2); the filtering works as expected with ANDs, but no matter what expression i put using the builder, no records ever show.
i.e. if I use this filter: filterExpressions.add("OpportunityId", Telerik.Web.UI.RadListViewFilterFunction.GreaterThanOrEqualTo, 2);
all items with id > 2 show up, but if I use this filter: filterExpressions.build().greaterThan("OpportunityId", 2);
nothing shows up, and the same items should be showing up because its the same expression
attached is a print of what chrome shows as the tree for the filterExpressions object, when using a composite builder expression with one OR
9 Answers, 1 is accepted
More info on filter expressions(might be bugs or by design, i cant tell):
If I'm filtering the same JSON to find out if ExperienceLevelId is null, I can't get the filters to work with filterExpressions.add("ExperienceLevelId", Telerik.Web.UI.RadListViewFilterFunction.IsNull);
the javascript object of filterExpressions shows the IsNull expression but every record shows up, regardless of its ExperienceLevelId being null or not. Could it have something to do with ExperienceLevelId being a numeric field?
I can get the desired behaviour by using filterExpressions.add("ExperienceLevelId", Telerik.Web.UI.RadListViewFilterFunction.EqualTo, null); instead.
I would suggest you to try using ClientDataSource for binding the RadListView on the client and modify the filter expression like shown in the demo below:
http://demos.telerik.com/aspnet-ajax/listview/examples/client/client-data-source-binding/defaultcs.aspx?product=listview
Regards,
Maria Ilieva
Telerik
Can you please share your ListView declaration as well as the related coded behind and client code? Thus we will be able to revise it locally and do our best to advise you further.
Regards,
Maria Ilieva
Telerik
Hi Maria, Thanks for the help,I went on to debug the telerik methods themselves and found what I think is something that might help on the flow the rebind method.
if you debug a listview.rebind() call, you'll be able to drill down through:
rebind -> _autoDataBind() -> _bindClientDataSource();
in there you'll have some instructions:
d.get_filterExpressions().clear();
d.get_filterExpressions().add(e);
if you enter that last one you'll see:
get_filterExpressions: function() {
var w = this;
var u = w._filterExpressions;
var v = u instanceof b.FilterExpression || u instanceof b.FilterEntry;
if (u === Object(u) && !v && (u.filters || u.logicOperator)) {
w._filterExpressions = c.translateFiltersRecursive(u);
} else {
if (!u || a.isEmptyObject(u)) {
w._filterExpressions = new b.FilterExpression();
}
}
return w._filterExpressions;
}
A group filter will evaluate to true at this line: var v = u instanceof b.FilterExpression || u instanceof b.FilterEntry;
So it will not satisfy all the next if's clauses: if (u === Object(u) && !v && (u.filters || u.logicOperator)) {
and will not call c.translateFiltersRecursive(u);, which sounds like something a group filter would do...
ALSO, "u" is a non null object, so it wont be returned as an empty filter in the else, it will just be returned as a FilterEntry of field:undefined, operation:undefined, value:undefined...
just a hint though, it might not mean anything.
Declaration:
<telerik:RadListView ID="RadListView1" ClientDataSourceID="RadClientDataSource2"
AllowPaging="true" PageSize="12" runat="server" RenderMode="Lightweight"
Skin="Bootstrap" ClientIDMode="Static">
<LayoutTemplate>
<div class="container">
<div class="main">
<ul id="itemPlaceholder" runat="server" class="jobs-listing grid">
<asp:PlaceHolder ID="offersContainer" runat="server"></asp:PlaceHolder>
</ul>
</div>
<br />
<div class="text-center">
<telerik:RadButton runat="server" CssClass="pagePrev"
ID="pagePrev" ButtonType="SkinnedButton" CausesValidation="False"
Skin="Bootstrap" Text="Prev" AutoPostBack="False">
</telerik:RadButton>
<telerik:RadButton runat="server" CssClass="pageNext"
ID="pageNext" ButtonType="SkinnedButton" CausesValidation="False"
Skin="Bootstrap" Text="Next" AutoPostBack="False">
</telerik:RadButton>
</div>
</div>
</LayoutTemplate>
<ClientSettings>
<DataBinding>
<ItemTemplate>
<li class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
<div class="jobs-content">
<div class="cs-media">
<figure>
<img alt="" style="width: auto; height: 100%;" src="#= ClientImageUrl #">
</figure>
</div>
<div class="cs-text" style="height: 225px">
<div class="cs-categories cs-color">#= ClientName #</div>
<div class="cs-post-title" style="width: 100%">
<h6><a href="/offers/Detail.aspx?id=#= OpportunityId #">#= OpportunityTitle #</a></h6>
</div>
<div class="cs-grid-job-type"><a href="" class="jobtype-btn">#= OpportunityType #</a></div>
<div class="post-options">
<span class="cs-location">#= CityName #, #= CountryName #</span>
<span class="cs-post-date">#= PublishDate #</span>
</div>
<div class="wish-list">
<button type="button" class="heart-btn shortlist" data-toggle="tooltip" data-placement="top" title="" data-original-title="Add to Shortlist"><i class="icon-heart-o"></i></button>
</div>
</div>
</div>
</li>
</ItemTemplate>
</DataBinding>
</ClientSettings>
</telerik:RadListView>
Data Source
<telerik:RadClientDataSource runat="server" ID="RadClientDataSource2">
<ClientEvents OnCommand="dataSourceCommand" OnRequestStart="requestStart" />
<DataSource>
<WebServiceDataSourceSettings>
<Select Url="/api/opportunities" RequestType="Get" />
<Insert Url="api/opportunities" RequestType="Post" />
<Update Url="api/opportunities" RequestType="Put" />
<Delete Url="api/opportunities" RequestType="Delete" />
</WebServiceDataSourceSettings>
The JSON this /api/opportunity brings is sampled in the posts above
the declarations on pageLoad() and radcodeblock
<script type="text/javascript">
function pageLoad() {
demo.initialize(
"<%= RadListView1.ClientID%>");
}
</script>
<telerik:RadCodeBlock runat="server" ID="RadCodeBlock1">
<script>
var updatedIDs = [], deletedIDs = [];
function requestStart(sender, args) {
var type = args.get_type();
var transport = sender.get_dataSourceObject().options.transport;
switch (type) {
case "read":
transport.read.url = "/api/opportunities/";
break;
case "create":
transport.create.url = "api/opportunities/";
break;
case "update":
transport.update.url = "api/opportunities/" + updatedIDs.shift();
break;
case "destroy":
transport.destroy.url = "api/opportunities/" + deletedIDs.shift();
break;
default: break;
}
}
function dataSourceCommand(sender, args) {
var commandName = args.get_commandName();
var id = args.get_commandArgument().id;
switch (commandName) {
case "update":
updatedIDs.push(id);
break;
case "remove":
deletedIDs.push(id);
break;
default: break;
}
}
</script>
</telerik:RadCodeBlock>
</DataSource>
</telerik:RadClientDataSource>
demo.initialize:
demo.initialize = function (listViewId) {
listView = $find(listViewId);
filterExpressions = listView.get_filterExpressions();
jQuery(".pageNext").click(function () {
listView.page(listView.get_currentPageIndex() + 1);
});
jQuery(".pagePrev").click(function () {
listView.page(listView.get_currentPageIndex() - 1);
});
}
and finally, the function that gets called to pdate the listview filters:
window.pageFilterChanging = function () {
filterExpressions
.clear()
.build()
.greaterThan("OpportunityId", 25)
.and()
.lessThan("OpportunityId", 30)
.or()
.group(function (builder) {
builder.notEqualTo("OpportunityTitle", "y")
.and()
.startsWith("OpportunityTitle", "F");
});
filterExpressions.add("OpportunityId", Telerik.Web.UI.RadListViewFilterFunction.GreaterThan, 0);
listView.rebind();
}
that last line is the one i debugged.
Client-side filtering is demonstrated in the RadListView Client-Side Web Service DataBinding Demo and explained in detail in the RadListView Client-Side Sorting and Filtering help topic.
Regards,
Maria Ilieva
Telerik
I have tested your approach in the online demo below and it works as expected:
http://demos.telerik.com/aspnet-ajax/listview/examples/client/webservicedatabinding/defaultcs.aspx
Regards,
Maria Ilieva
Telerik