How can I move my Flex app into multiple layers?
So in general - Flex has been easy for me to grok since it first came out. It's gotten easier over time, but normally, the most trouble I have is having to look up an argument to see how to do something in particular.
However - one thing has troubled me for a while now. I've solved this problem before in earlier Flex apps, but I really don't think I have my head around it yet. I'm asking for help and some opinions here on what would be the 'best practice', and I more than understand that there will be more than one answer.
TimeTracker updated (again!)
Well I'm done. Mostly anyway. I set out when creating this application to get more familiar with SQLite, and I've certainly done that. Today I think the TimeTracker application is finally complete. A lot of folks helped out with it so I definitely can't take all (or most) of the credit.
In this final build I added a few more features, including, the CSV export, which was pretty fun to build. Creating the CSV string was trivial. I even went the extra step and had the string properly handle data with commas and quotes.
To save the file, I used this excellent article by Mike Chambers. It's pretty trivial actually to ask a user to pick a file and then save the data. AIR really does make this simple.
I also added some basic validation to the forms in the application to make it a bit more stable.
I will warn folks though - I wrote this to learn, and I wrote it as I needed a way to track hours. But frankly, I wouldn't trust my code. If you want to really use it, I beg you to use the CSV export feature to make backups. I don't want to be responsible for someone losing all their data.
It was also suggested that I put this application up on RIAForge. As I have an "in" with the manager, I was able to get the project approved pretty quickly. You can download both the AIR file and source here:
http://timetrackerair.riaforge.org/
Now on to my next AIR project.
TimeTracker Updated - Dealing with long strings in Flex DataGrids
I've updated TimeTracker again. This version includes the code fixes by Sid Wing (thanks!) which was part cleanup and a fix to the mx:Legend. I agree with Sid's comment that the docs could certainly be clearer.
I also removed the 'Enter key submits hours' thing so folks could enter multiline task descriptions. This is where I ran into an issue with the Flex DataGrid. It refused to correctly render the text in a readable format. Thanks to Scott Stroz for pointing out the variableRowHeight attribute for Flex DataGrids.
<mx:DataGrid id="todayshours" dataProvider="{todaysHoursData}" width="100%" height="100%" sortableColumns="true" variableRowHeight="true">
Oh my sweet little adorable Flex DataGrid, is there anything you cannot do?
I also added word wrap to the description columns as well as sorting. (Although I bet date sorting isn't quite right.)
Next up is the CSV export. After that is done I plan on releasing the code to RIAForge since there seems to be some interest.
TimeTracker Updated, and how I did date filtering in SQLite/AIR
Sometime ago I began work on a simple AIR tool to help me record my hours. It's been a while since I worked on it, but this weekend I decided to take another look at a nagging issue that I had never resolved. How do I do date filters in SQLite? Specifically, the "Enter Hours" screen should only show the hours you entered for today. (I plan on adding a Reports tab later to let you browse hours and generate reports.)
I worked and worked and worked on this issue before, but figured a fresh look may help. I finally got it working. I used the strftime function, which is really meant to format dates, but I was able to use it in the WHERE clause as well. This is the final code I ended up with:
hourDataStatement.text = 'select hours.description, hours.hours, hours.date, projects.name as project, clients.name as client from hours, projects, clients where hours.projectidfk = projects.id and projects.clientidfk = clients.id ' +
'and strftime("%d",date) = strftime("%d",date("now")) ' +
'and strftime("%m",date) = strftime("%m",date("now")) ' +
'and strftime("%Y",date) = strftime("%Y",date("now")) ' +
'order by date desc';
In case that doesn't make sense, what I've done is added where clauses that do:
where 'format the date to show just day == the day of today' AND 'format the date to show just the month == the month of today' AND 'format the date to show just the year == the year of today'
Not incredibly elegant, but it worked!
During my testing I also ran into another issue. One thing I tell people about Flex development is - it is incredibly easy for the most part. All you have to do is get comfortable with the tag set and have an idea of what you can do in ActionScript. What is difficult is getting used to asynchronous operations. The idea that - I can run some remote function but I have to write a function to handle the result. Maybe it's just me, but time and time again this trips me up.
The problem I ran yesterday involved the start up code for the application. I had deleted my old database so everything was run fresh. I got an error stating that the schema had changed. I think I know why. My old code did this:
- Open an async connection, when open, run SetUp()
- SetUp would create new tables if necessary
- Setup used a Synch connection.
- When done, continue on the app
- The rest of the app used the original asynch connection.
So my take on the bug was - the original async connection got "confused" when the db was changed underneath it. I edited my code a bit so as we now do:
- Open synch connection and make tables.
- When done, open the new asynch connection.
And this corrected the problem. I've included both the source and the AIR installer for the latest version. Now I'm very happy as I get to play with charts and generating reports!
Adobe Developer Week
Wow, I just found this out myself, but it may be old news. Next week Adobe is hosting a week full of developer sessions you can attend via Connect.
Topics cover ColdFusion, AIR, Flex, Flash, and other items. If you can't sign up for a session (or be there when it happens), Adobe will be providing recordings 5 days later.
Again - wow!
Ask a Jedi: Flex released - where do I go next?
Jason asked a very interesting question considering last night's releases by Adobe.
If you were a CF developer, but wanted to start working with Flex 3 (having little or no experience with it) how would you go about starting? There are a dizzying array of links, tutorials, etc out there (lots of older CF and Flex versions). I like to focus on getting up and running with CF 8 and Flex 3, for obvious reasons. You know of a good place to start?
Flex 3, AIR Released
The title says it all - and just about every other blog out there. Adobe has released both the third edition of Flex, as well as the very cool AIR. My readers know how I feel about these products, so I won't say much now (and plus I want to go to bed ;), but get downloading!
Time Tracker AIR Update, and what I learned about label functions and optional args in Flex
I've got a big update to the my little Time Tracker AIR application, thanks mostly to Kyle Hayes. He gave some UI loving to the app - see below:

I've done a bit more cleanup. One of the things I fixed was my duplicate labelFormatter. The labelFunction feature is one of the neatest things in Flex. When it comes to a control that takes a set of data, you can say, "When displaying X, call this function." Your function can then do stuff like, "If the row of data has a price more than 100, mark it (Expensive!)". You get the idea. What was bugging me though was that I wanted to use the same labelFunction for my DataGrid and my ComboBox. But the DataGrid passes 2 arguments to it's label function, and the ComboBox passes one. I wrote two functions which both did the exact same thing. Turns out (and I found this online but forgot to bookmark where) there is a simpler solution - just mark the section argument as optional. Here is an example from my code:
private function projectLabel(item:Object,col:DataGridColumn=null):String {
return item.project + " (" + item.client + ")";
}
In this code block, the second column has an optional value. It is optional because we define a default value to use in case one isn't passed.
Anyway, most of my changes are pretty small. I switched to using States to handle "loading" versus 'real' application. I also made the Hour panel notice if you have no active projects. (Need to double check that I have the active flag in there.)
I'm still struggling with the dates though, and I've had some folks help me out on my other post, so hopefully that will get corrected soon.
So now I'm going to turn my attention to a reports page. I've only played with Flex charts a bit, but I'm looking forward to it. I'd especially love to be able to find out which client/project paid me the most money, something that isn't possible with the current system I use.
I know I keep saying the following, but I should repeat it anyway. I'm really loving AIR and Flex. But please consider my code to be anything but best practice.
Working with Flex, AIR, and SQL (2)
It's been a little while, but I've gotten around to working more on my Time Tracker AIR application, first discussed here. As a recap, my intention was to build a simple time tracker that would let me enter hours for projects and clients. The real goal was to learn more about SQLite and the AIR connection to it.
I've made some updates to the application and learned a bit on the way.
The first issue I ran into was my database setup code. My original code made one table, and when the table was done being created (if it needed to be), the application entered it's normal operating mode. This became a problem when I wanted to make two tables. If you remember, I had created an asynchronous database connection. I wasn't able to run both SQL statements in one execution so I had to two executions. How would I know when to start my program? I could use a bunch of flags, but that seemed like a mess.
So what I did was compromise. I kept one database connection in asynchronous mode. This would be my main connector to the database. In my startup code though I created another connection - one that was synchronous. This let me setup my tables and begin the application proper when done.
I also discovered that you want to be sure you think about your table structure. While it is possibly to modify tables, I just simply wrote a temp "drop table" code segment that I keep commented out most of the time.
I ran into this issue again on the new Projects page. This lets me create projects that are tied to clients. On loading the panel though we need to get both clients and projects. The issue was this though - what if projects loaded very quickly, but clients didn't? If you clicked to edit a project, I wouldn't be able to display the client drop down. So for this page I used a flag. I only allow you to edit projects once clients have finished loading. (As a quick release note, the Client filter on this page doesn't work, but the Active filter does.)
I added the Hour Entry page yesterday. It lets you add hours to a project. (Again though, no validation, so be sure to pick everything.) I loved how Flex had a built in numeric stepper control. It was perfect for this. Ditto for the calendar.
I ran into one more database issue here. I wanted to show the hours you entered today. (The reports page will let you view all hours, when I get to coding it.) But I'm having issues with date comparisons and SQLite. For now it will show everything.
I've include the AIR installer and full source code in the package. Enjoy. Again, assume I wrote horrible Flex code. I'm going to blame the Saints for not making it to the playoffs for my lack of Flex skills.
Flex 3 / AIR Pre-release tour
If you've read my blog at all you know I've been really getting into Flex 3 and AIR. I encourage any "pure CF" developer to take a look at these technologies as they really, really, make front end development a heck of a lot cooler. Both products are getting close to final release, and in preparation, Adobe's Platform Evangelist team is traveling around the country giving demos and - of course - giving away some cool schwag. For a list of locations and dates, see http://flex.org/tour/. Looks like nothing in Louisiana though, which is too bad since it's Mardi Grad season!
Any of my readers going?

