In this article I will explain how to implement Price Range Slider in ASP.Net using jQuery Slider plugin and jQuery AJAX.
When the price range is changed inside the slider, the items will be filtered from database using jQuery AJAX.
Database
The Products table has the following schema. This table will store the Product details.
Note: You can download the database table SQL by clicking the download link below.
HTML Markup
The HTML Markup mainly consists of an ASP.Net DataList control which will be used as a Template to recreate items when the slider range is changed. The DataList is placed inside a hidden DIV.
Other than that are three DIV controls price_slider_value, price_slider and dvProducts for populating the slider, the selected range details and the actual products for that range respectively.
Finally there’s DIV for displaying modal background during the AJAX calls.
<div id="price_slider_value" style="width: 400px">
</div>
<div id="price_slider">
</div>
<hr />
<div id="dvProducts">
</div>
<div style="display: none">
<asp:DataList ID="dlProducts" runat="server" RepeatLayout="Table" RepeatColumns="3"
CellPadding="2" CellSpacing="20">
<ItemTemplate>
<table class="item" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center" class="header">
<span class="name">
<%# Eval("Name") %></span>
</td>
</tr>
<tr>
<td align="center" class="body">
<img class="image" src="" alt="" />
</td>
</tr>
<tr>
<td class="footer" align="center">
<span class="button"></span>
<input type="hidden" class="is_used" value="0" />
<input type="hidden" class="product_id" value='<%# Eval("ProductId")%>' />
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
</div>
<div class="modal">
<div class="center">
<img alt="" src="loader.gif" />
</div>
</div>
Namespaces
You will need to import the following namespaces.
C#
using System.Data;
using System.Data.SqlClient;
using System.Web.Services;
using System.Configuration;
VB.Net
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.Services
Imports System.Configuration
Binding a dummy record to the DataList
In the Page Load event, I am binding a dummy record to the DataList control. This is very necessary as jQuery needs some HTML content which it can replicate the data fetched via jQuery AJAX.
There’s also a protected variable RepeatColumns which is set with the value of the RepeatColumns property of the DataList and as this value will be used in client side script.
C#
protected int RepeatColumns;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.BindDummyItem();
}
}
private void BindDummyItem()
{
DataTable dummy = new DataTable();
dummy.Columns.Add("ProductId");
dummy.Columns.Add("Name");
dummy.Columns.Add("Price");
int count = dlProducts.RepeatColumns == 0 ? 1 : dlProducts.RepeatColumns;
for (int i = 0; i < count; i++)
{
dummy.Rows.Add();
}
dlProducts.DataSource = dummy;
dlProducts.DataBind();
this.RepeatColumns = dlProducts.RepeatColumns == 0 ? 1 : dlProducts.RepeatColumns;
}
VB.Net
Protected RepeatColumns As Integer
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not IsPostBack Then
Me.BindDummyItem()
End If
End Sub
Private Sub BindDummyItem()
Dim dummy As New DataTable()
dummy.Columns.Add("ProductId")
dummy.Columns.Add("Name")
dummy.Columns.Add("Price")
Dim count As Integer = If(dlProducts.RepeatColumns = 0, 1, dlProducts.RepeatColumns)
For i As Integer = 0 To count - 1
dummy.Rows.Add()
Next
dlProducts.DataSource = dummy
dlProducts.DataBind()
Me.RepeatColumns = IIf(dlProducts.RepeatColumns = 0, 1, dlProducts.RepeatColumns)
End Sub
WebMethod to handle AJAX calls from jQuery and fetch
The following web method handles the jQuery AJAX calls when slider range is changed. It simply fetches the records from the database and returns the XML to the client.
During the first AJAX call the minimum and the maximum values are 0 and hence all records are fetched and when the minimum and the maximum values from the jQuery Slider is sent the records are filtered based on the supplied values.
Along with the data, the minimum and the maximum price of the products is also sent so that the slider can be implemented with the minimum and maximum range.
C#
[WebMethod]
public static string GetProducts(int start, int end)
{
string strConnString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
DataSet ds = new DataSet();
using (SqlConnection con = new SqlConnection(strConnString))
{
string query = "SELECT * FROM Products WHERE (Price BETWEEN @Start AND @End) OR (@Start = 0 AND @End = 0)";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("@Start", start);
cmd.Parameters.AddWithValue("@End", end);
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
sda.Fill(ds, "Products");
}
}
}
DataTable dt = new DataTable();
dt.TableName = "Range";
using (SqlConnection con = new SqlConnection(strConnString))
{
string query = "SELECT MIN(Price) [Min], MAX(Price) [Max] FROM Products";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
sda.Fill(dt);
}
}
}
ds.Tables.Add(dt);
return ds.GetXml();
}
VB.Net
<WebMethod()> _
Public Shared Function GetProducts(start As Integer, [end] As Integer) As String
Dim strConnString As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
Dim ds As New DataSet()
Using con As New SqlConnection(strConnString)
Dim query As String = "SELECT * FROM Products WHERE (Price BETWEEN @Start AND @End) OR (@Start = 0 AND @End = 0)"
Using cmd As New SqlCommand(query)
cmd.Connection = con
cmd.Parameters.AddWithValue("@Start", start)
cmd.Parameters.AddWithValue("@End", [end])
Using sda As New SqlDataAdapter(cmd)
sda.Fill(ds, "Products")
End Using
End Using
End Using
Dim dt As New DataTable()
dt.TableName = "Range"
Using con As New SqlConnection(strConnString)
Dim query As String = "SELECT MIN(Price) [Min], MAX(Price) [Max] FROM Products"
Using cmd As New SqlCommand(query)
cmd.Connection = con
Using sda As New SqlDataAdapter(cmd)
sda.Fill(dt)
End Using
End Using
End Using
ds.Tables.Add(dt)
Return ds.GetXml()
End Function
jQuery AJAX and Client Side implementation
Below is the client side implementation where the actual job is done. As soon as the page loads an AJAX call is made to the client with 0 values for both minimum and the maximum using the GetRecords function and hence all records are loaded.
Using the minimum and the maximum price value from the server, the jQuery slider is implemented and inside the stop event handler of the jQuery slider the GetRecords method is again called with the minimum and the maximum values of the slider.
Based on the DataList RepeatColumns property value, the hidden DataList Items are cloned and appended to the page with the values fetched from the server.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js" type="text/javascript"></script>
<link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/themes/excite-bike/jquery-ui.css"
rel="stylesheet" type="text/css" />
<script type="text/javascript">
var min = 0;
var max = 0;
$(function () {
//Get records for all prices.
GetRecords(0, 0);
});
function SetSlider() {
//Initialize the slider
$("#price_slider").slider({
min: min,
max: max,
step: 5,
values: [min, max],
stop: function (event, ui) {
var start = parseInt(ui.values[0]);
var end = parseInt(ui.values[1]);
$("#price_slider_value").html("Rs." + ui.values[0] + " - Rs." + ui.values[1]);
//When slider is stopped then get records for range.
GetRecords(start, end);
},
slide: function (event, ui) {
if ((ui.values[0] + 5) >= ui.values[1]) {
return false;
}
}
});
//Display the minimum and maximum values.
$("#price_slider_value").html("Rs." + min + " - Rs." + max);
}
function GetRecords(start, end) {
$(".modal").show();
$.ajax({
type: "POST",
url: "Default.aspx/GetProducts",
data: '{start: ' + start + ', end: ' + end + '}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess,
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
}
function OnSuccess(response) {
var xmlDoc = $.parseXML(response.d);
var xml = $(xmlDoc);
if (min == 0 && max == 0) {
//Only for the first time set the minimum and maximum values.
min = parseInt(xml.find("Range").eq(0).find("Min").text());
max = parseInt(xml.find("Range").eq(0).find("Max").text());
SetSlider();
}
var products = xml.find("Products");
var repeatColumns = parseInt("<%=RepeatColumns %>");
$("#dvProducts").html("<div id = 'empty'>There are no products available for the selected price range.</div>");
if (products.length > 0) {
//Copy the DataList HTML into the DIV.
$("#dvProducts").html($("[id*=dlProducts]").parent().html());
}
$("#dvProducts > table").removeAttr("id");
var rowCount = Math.ceil(products.length / repeatColumns);
var j = 0;
products.each(function () {
var product = $(this);
var row = $("#dvProducts > table .item:last").closest("tr");
if ($(".is_used[value='1']", row).length == repeatColumns) {
row = $("#dvProducts > table tr").eq(0).clone();
$(".is_used", row).val("0");
$("#dvProducts > table").append(row);
j = 0;
} else {
row = $("#dvProducts > table .item:last").closest("tr");
}
var cell = $(".item", row).eq(j);
$(".name", cell).html(product.find("Name").text());
var productId = product.find("ProductId").text();
$(".product_id", cell).val(productId);
$(".button", cell).text(product.find("Price").text());
$(".is_used", cell).attr("value", "1");
var img = $(".image", cell);
img.attr("src", "images/" + productId + ".png");
j++;
});
$("#dvProducts > table .is_used[value='0']").closest(".item").remove();
$(".modal").hide();
}
</script>
CSS styles
Below are the CSS classes that were used for this article.
<style type="text/css">
body
{
font-family: Arial;
font-size: 10pt;
margin: 0;
padding: 0;
}
.loader
{
height: 50px;
width: 100px;
}
.item
{
width: 202px;
border: 1px solid #ccc;
box-shadow: 2px 2px 8px 2px #ccc;
}
.item .header
{
height: 30px;
background-color: #9F9F9F;
color: #fff;
}
.item .body
{
width: 200px;
height: 200px;
}
.item .image
{
height: 200px;
width: 200px;
}
.item .footer
{
height: 50px;
}
.button, .button:hover
{
height: 45px;
padding: 10px;
color: White;
line-height: 23px;
text-align: center;
font-weight: bold;
cursor: pointer;
border-radius: 4px;
text-decoration: none;
background-color: #9F9F9F;
border: 1px solid #5C5C5C;
}
#price_slider, #price_slider_value
{
width: 400px;
margin: 5px;
}
#empty
{
display: block;
width: 400px;
background-color: #9F9F9F;
color: #fff;
height: 30px;
line-height: 30px;
margin: 5px;
text-align: center;
}
.modal
{
position: fixed;
z-index: 999;
height: 100%;
width: 100%;
top: 0;
background-color: Black;
filter: alpha(opacity=60);
opacity: 0.6;
-moz-opacity: 0.8;
}
.center
{
z-index: 1000;
margin: 300px auto;
padding: 10px;
width: 130px;
background-color: White;
border-radius: 10px;
filter: alpha(opacity=100);
opacity: 1;
-moz-opacity: 1;
}
.center img
{
height: 128px;
width: 128px;
}
</style>
Demo
Downloads