Tuesday, December 11, 2012
So I’m a huge fan of a Generic Template Pattern in .NET but with ColdFusion and am faced with a challenge. How to implement inheritance and polymorphism in ColdFusion. Adobe has a great article on the basics of inheritance in ColdFusion.
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=buildingComponents_30.html
In this article they extend an Employee. There are 3 types of employees. Employee, manager, and president. President extends manager, manager extends employee.
Go to the site above and create this example. (or you can download mine from CodePlex)
ColdFusion\Skyhook_ColdFusion_TemplateMethod
So I just started learning about ColdFusion and one of the first thing I had to do was bind some data to a grid or table. So being an ASP.net developer I looked for the ColdFusion equivalent to an ASP GridView. I found that ColdFusion has a CFGrid control that would do what I was looking for. In this post I am going to go over some of the different ways to use the CFGrid and the pro/cons that I have discovered.
Bind data using the Query property
So in my attempt to learn the CFGrid I started with using CFdirectory to get a list of files on the C:. With that list I set the CFGrid’s data source to it.
CfGrid_Query.cfm
<cfform enctype="multipart/form-data" method="post">
<cfset fileLocation = "c:">
<cfdirectory action="list" sort="datelastmodified DESC" directory="#fileLocation#" name="files" listinfo="all" >
<cfset fileQuery = QueryNew("Name", "VarChar" )>
<cfset i=1>
<cfloop query="files">
<cfset newRow = QueryAddRow(fileQuery, 1)>
<cfset temp = QuerySetCell(fileQuery, "Name", files.name, i)>
<cfset i = i + 1>
</cfloop>
<div>
This grid is using Query to bind its data
</div>
<div>
<cfgrid name="cgFiles" format="html" selectmode="row" striperows="yes" width="700" query="fileQuery">
<cfgridcolumn name="Name" header="Name" />
</cfgrid>
</div>
</cfform>
This code above does the following things:
- First we use cfdirectory to get a list of all the files/folders on the C:. This could be bound directly to the cfgrid at this point using Query but I wanted to add a column for preview icon and hyperlink so I create a new Query (similiar to DataTable in .NET) to put all these values in.
- The new Query has only the Name column in this example. The cfloop loops through the results and creates a corresponding row in the new Query.
- Bind the Query to the CfGrid using the Query attribute.
Pros
- Pretty easy to bind to the grid with a list or query
- Grid looks pretty right out of the box without any setup
- Column sorting is built in.
Cons
- When using the Query attribute to bind the data you can’t use the built in paging.
Bind data using the Bind property with a CFC
For my project I would need to have paging. So using the Query attribute isn’t going to work. Thankfully there is another way to bind data to the CfGrid that will use the built in paging. For this example I have created a CfComponent that has a CfFunction that does the same thing as the previous grid.
CfGrid_BindCFC.cfm
<cfgrid name="cgFiles" height="300" format="html" selectmode="row" striperows="yes" width="700" bind="cfc:Skyhook_ColdFusion_Controls.TestCom.GetData({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})">
<cfgridcolumn name="Name" header="Name" />
</cfgrid>
TestCom.cfc
<cfcomponent>
<cffunction name="GetTestString" access="remote" returntype="string">
<cfset testString = "Testing">
<cfreturn testString>
</cffunction>
<cffunction name="GetData" access="remote" returntype="any">
<cfargument name="page" default="1">
<cfargument name="pageSize" default="10">
<cfargument name="gridsortcolumn" default="LastModified">
<cfargument name="gridsortdir" default="DESC">
<cfset fileLocation = "c:">
<cfdirectory action="list" sort="datelastmodified DESC" directory="#fileLocation#" name="files" listinfo="all" >
<cfset fileQuery = QueryNew("Name", "VarChar" )>
<cfset i=1>
<cfloop query="files">
<cfset newRow = QueryAddRow(fileQuery, 1)>
<cfset temp = QuerySetCell(fileQuery, "Name", files.name, i)>
<cfset i = i + 1>
</cfloop>
<cfset result = QueryConvertForGrid(fileQuery, page, pageSize)>
<cfreturn result>
</cffunction>
</cfcomponent>
So with the above code I am setting the Bind property on the CfGrid to cfc:Skyhook_ColdFusion_Controls.TestCom.GetData({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection}).
cfc:componentPath.functionName(parameters)
To break this down, first we need to choose if we are going to bind to a cfc, url, or javascript. For this example I am using a CFC that will be returning a struct. This struct contains 2 parts. The first part is the Query and its data. The second part is the Total Row Count for the query. The CfGrid will would bind via cfc if you are returning a struct with both parts. Simply binding to a query of the data will not work.
The componentPath is the dot delimited path from the web root or the directory that contains the current page. NOTE: You do need to make sure that ColdFusion Administrator has mappings to the CFC directory. (This threw me off for a while)
The functionName and parameters for the CfGrid will be passing the page you are currently on, the page size, sort column, and sort direction. When binding to the CfGrid your function must have these 4 parameters on your function.
The CFC function does the same thing as the previous grid. It gets all the files/folders from the C: and returns it.
As you can see in the screenshot, I now have paging on the grid. (Default is set to 10 in function)
To download the source code visit my CodePlex page. This example is under ColdFusion/Skyhook_ColdFusion_Controls
http://skyhookprojectviewer.codeplex.com/SourceControl/BrowseLatest
Tuesday, December 4, 2012
I always have to google this whenever I need it. So instead of searching every time I am putting it here. I originally got this from Reign Water Designs.
Check the link here:
http://www.reignwaterdesigns.com/ad/tidbits/hacks/css_center.shtml
First
This will only work if the DOCTYPE is XHTML Transitional or Strict. IT WILL NOT WORK if your doctype is HTML 4.x. Here is an example of what it should look like:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
NEXT!
Put this at the top of your CSS file.
#html, body {
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
width:980px;
height: 100%;
margin: auto;
}
Thursday, November 29, 2012
Went to training at The Forge yesterday and did a Day in the life of Agile with Pillar. It was pretty good.
Check them out at: http://pillartechnology.com/
Abstract:
A single-day agile project simulation that is engaging, educational, provocative, and fun. This simulation introduces concepts like time-boxed iterations, User Stories, collective estimation, commitment to a product owner for iteration scope, formal verification ritual at iteration conclusion, tracking velocity, and making results big and visible through charts. The exercise is designed to simulate not only how agile teams and practices work, but the inevitable challenges that arise as teams attempt to adopt such practices.
One of the best parts of this training was getting some hands on experience with agile. We used a program called Scratch to create an arcade video game. Our team chose Frogger. We had 3 iterations at 20 minutes each. I think we did pretty good but in the panic of trying to get a bunch done in only 20 minutes made it interesting.
To check out our project, I uploaded it to my CodePlex site
Download Source Code (Under Scratch/Frogger)
Cool class! I highly recommend if you get the opportunity.
Wednesday, November 28, 2012
So recently I had an ASPX page that could be visited by two different user types. User type A would use Master Page 1 and user type B would use Master Page 2. So I put together a proof of concept to see if it was possible to change the MasterPage in code. I found a great article on the Microsoft ASP.net website.
Specifying the Master Page Programmatically (C#) by Scott Mitchell
So I created a MasterPage call Alternate.Master to act as a generic place holder. I also created a Master1.Master and a Master2.Master. The ASPX page, Default.aspx will use this MasterPage. It will also use the Page_PreInit event to programmatically set the MasterPage.
1: protected void Page_PreInit(object sender, EventArgs e) {
2: var useMasterPage = Request.QueryString["use"];
3: if (useMasterPage == "1")
4: MasterPageFile = "~/Master1.Master";
5: else if (useMasterPage == "2")
6: MasterPageFile = "~/Master2.Master";
7: }
In my Default.aspx page I have the following links in the markup:
1: <p>
2: <asp:HyperLink runat="server" ID="cmdMaster1" NavigateUrl="~/Default.aspx?use=1" Text="Use Master Page 1" />
3: </p>
4: <p>
5: <asp:HyperLink runat="server" ID="cmdMaster2" NavigateUrl="~/Default.aspx?use=2" Text="Use Master Page 2" />
6: </p>
So the basic idea is when a user clicks the HyperLink to use Master Page 1, the default.aspx.cs code behind will set the property MasterPageFile to use Master1.Master. The same goes with the link to use Master Page 2.
It worked like a charm!
To see the actual code, feel free to download a copy here:
Project Name: Skyhook.MultipleMasterPagesWeb
http://skyhookprojectviewer.codeplex.com
Wednesday, October 3, 2012
TypeScript looks like a great start to evolving javascript. I am going to start playing with it seeing what it is like. This is the post I will update will all the resources I've found.