Background
Why did I bother doing this when there is Atlas, Anthem, etc…for ASP.NET?
I work with a lot of designers who are in love with Ruby On Rails, and one of the features that comes along with ROR is the integration with the script.aculo.us library. I have to admit that some of the built-in animation can be kind of neat. So in turn, I built a couple controls for ASP.NET. I ran into the issue that there were about a million articles for PHP but none for ASP.NET, so I'm going to change that.
The code attached is really simplified so that you understand the concepts; there are a lot of errors that can occur as well as some database issues. I also used Access as the database (which I hate!), but seemed to be the best way to illustrate my point. If you get errors, it's most likely because of the permissions set on your development computer.
Introduction
I decided to use a simple concept for this article, and the first thing that came to mind was baseball batting orders (don't ask me why).
Imagine that you have several players on your team and want to reorder the batting order so your best players can lead off! That's what this tutorial will do.
Using the code
The database
Again, the database is really simple. All we have here is a unique "player_id
", "player_name
", "player_position
", and "player_battingorder
". The "player_battingorder
" is what we will reorder on drag and drop, "player_id
" is used for reference, and the rest are just used for display purposes.
Simple data access
I'm going to assume that you know a little bit about Repeater
s and simple queries to a database. If you don't, then I suggest you look that up first! This should all look familiar and rather boring! We are just grabbing all of the players from the table "Players" and ordering by "player_battingorder
".
Private Function GetBattingOrder()
Dim ds As New DataTable
Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" &_
"data source=" & Server.MapPath("/Database/DB.mdb"))
Dim adap As OleDbDataAdapter
adap = New OleDbDataAdapter("SELECT * FROM Players " &_
"ORDER BY player_battingorder ASC", conn)
adap.Fill(ds)
Return ds
End Function
Next, let's create a simple Repeater
and bind it on the Load
event of the page. I'm going to use an ordered list so we can see what batting order they have.
<asp:Repeater ID="rptPlayers" runat="server">
<HeaderTemplate>
<ol>
</HeaderTemplate>
<ItemTemplate>
<li><%#Eval("player_name")%> - <%#Eval("player_position")%></li>
</ItemTemplate>
<FooterTemplate>
</ol>
</FooterTemplate>
</asp:Repeater>
Okay, so if you ran your web app now, all you would see is a list of players in the DB.mdb. I'm not impressed by this either! Let's make this thing drag and drop.
Drag and drop
So, the most important thing you need for drag and drop is the script.aculo.us library. You can get it here, I've also included it with the source above. Put all of those files into a "js" folder in your root directory and input the following text into your head
tag of the default.aspx page.
<head runat="server">
<title>Script.acu.lous Test</title>
<script src="js/prototype.js" type="text/javascript"></script>
<script src="js/effects.js" type="text/javascript"></script>
<script src="js/dragdrop.js" type="text/javascript"></script>
</head>
Now, the rest of the stuff I'm going to show you is spelled out in the Usage Page, but I'm going to condense it in a quick way that applies to our code! We need to adapt the following code right before the body of our page…
<script type="text/javascript" language="javascript">
Sortable.create("NAME OF LIST/CONTAINER",{tag:'TAG WE ARE DRAGGING',
constraint:false,onUpdate:update})
function update(){
var options = {
method : 'post',
parameters : Sortable.serialize('NAME OF LIST')
};
new Ajax.Request('PAGE TO POST TO', options);
}
</script>
A couple things that you need to note from this…..You need to give the container in which you are dragging an ID, so for our current header, we need to give the ol
an ID in our HeaderTemplate
:
<HeaderTemplate>
<ol id="players">
</HeaderTemplate>
Another thing you need to know is that in the update function, each of the items needs to have a unique ID so that we can resave the order. It needs to have a title followed by an underscore, like this: "field"_"fieldid"…so ours will look like "player_player_id". So you're going to change your ItemTemplate
of the Repeater
to look like this:
<ItemTemplate>
<li id="player_<%#Eval("player_id")%>">
The finished Repeater
should look like this:
<asp:Repeater ID="rptPlayers" runat="server">
<HeaderTemplate>
<ol id="players">
</HeaderTemplate>
<ItemTemplate>
<li id="player_<%#Eval("player_id")%>">
Now that this is all done, let's use the values above to change that JavaScript function that I showed you earlier.
<script type="text/javascript" language="javascript">
Sortable.create("players",{tag:'li',constraint:false,onUpdate:update})
function update(){
var options = {
method : 'post',
parameters : Sortable.serialize('players')
};
new Ajax.Request('SaveBattingOrder.aspx', options);
}
</script>
So now that this is all done, you can drag and drop, but it doesn't save!
The reason why this is happening is because we never created the page to post to. If you notice the script above, I used the page called "SaveBattingOrder.aspx". So, let's create the page to handle the reorder. You have to know that the JavaScript function on Default.aspx sends the list of player_ids in a format that looks like this: "2, 3, 1,4". We can capture that by doing the following:
Dim battingorder As String() = Request.Form(0).Split(",")
So let's load all of these IDs into an array and loop through each item. As we loop through each item, let's save the players' batting order position and add one to the previous batting order. I'm going to rush through the rest since a lot of it is some simple database update code.
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim battingorder As String() = Request.Form(0).Split(",")
Dim strsql As String = ""
Dim intorder As Integer = 1
Dim conn As New OleDbConnection
conn = openConnection()
For i As Integer = 0 To battingorder.GetUpperBound(0)
SaveBattingOrder(conn, "UPDATE Players set player_battingorder = " &_
intorder & " Where player_id = " & battingorder(i))
intorder = intorder + 1
Next
closeConnection(conn)
End Sub
I'll have some quick database access functions in the source...but you should know how these work so I won't explain it too much.
We're done! Test it out and enjoy!!
Points of interest
A couple things you'll notice on the script.aculo.us site is that you can do a lot of cool animations along with this drag and drop script. Lastly, I am working on building some custom controls to wrap the script.aculo.us scripts into the ASP.NET controls; if anyone wants to help out, send me a comment below!
When I'm done, I'll be sure to post the code on here as well.
History
- 9/2/2007 - Article created.