The amazing adventures of Doug Hughes

I'm Stumped

One thing about OO implementing an MVC architecture in a stateless environment has eluded me. How does one cleanly manage interactions between the client and the server once the client has received its rendered HTML?

Consider this; I have a requirement in a current project to show several tables of data.

Data in these tables need to be sortable. When you click on a column header the data in the table will refresh and be sorted according to the data in the column.

The table of data also needs to be filterable. A filter could be applied to the data to show only rows where the last name starts with “H” or perhaps where some action is required.

Lastly the data displayed in the table needs to be nicely printable as a PDF or to FlashPaper. The resulting printed version would reflect the current state of the table showing only the filtered and sorted data.

An important consideration is that the data displayed in these tables will change throughout the application. For instance, in one case you might be viewing a table of users. Each user’s name might be a link to another page. Or, you might see a table of categories with each category having a checkbox you could select. (In this latter case the table would be shown in a form and some form action would deal with the selected categories.)

The point is that I want a generic system to flexibly create these storable, filterable, paginated tables.

Traditionally, I would probably just write some code that output a query into an HTML table. The output code would be one-off and written to let me do exactly what I need. So, if I needed a user’s name to be a link I’d simply surround it with a link tag. The column headers would be links back to the same page and would cause the server to rerun the query, but sorting it according to the selected columns. To filter data I’d have a form or links that would ultimately reload the page again to filter the data.

Because you can’t generate FlashPaper or PDFs directly from a browser (at least not using JavaScript), I would, when the user decided to print the table, once again, reload the page to rerun the query but this time have different display logic that would generate the PDF and send it to the user.

There’s nothing really wrong with this except that it’s repetitive, wasteful (in terms of network, CPU and database utilization), and rather procedural. There are many aspects of each of these tables that are repeated from table to table (the styles, the logic to output rows, the fact that the data can be filtered, the JavaScript to sort the data, the need for printing, the framework for making the requests to the server, and more).

Wouldn’t it be really nice to have something (a component or custom tag or JavaScript library?) which I could throw a set of data and configuration information at and have it be able to output a table that did exactly what I wanted?

One of the tenets of Object Oriented Programming is encapsulation. In a nutshell encapsulation means to hide your object’s implementation. Whatever uses your object shouldn’t care about how your object does its job, just that the job is done (and done correctly). So, with my tables of data, I want to encapsulate the process of creating the table and all the logic involved with sorting and filtering and printing it. I really only want to define what’s different between tables and have some other system automatically handle it.

What’s befuddling me is that the requirements genuinely requires interaction with the server from the client at least to print data.

In an effort to work through this problem let’s say that I temporarily forget that there is a requirement to view the table and pretend that I’m only working with data on the server. I could create a table component with an interface like this:

Table = init(data data, tableConfiguration Config) This would be a constructor for the Table. When constructed the table would receive a set of data and configuration settings. For now, I’m going to ignore the format of the data. You can imagine it’s a query or XML if that makes you feel better, but I don’t think it’s necessary yet. The configuration settings would probably specify column names in the table and the column’s datatype.

sort(iSort Sorter) This method on the Table component would receive an object that implemented an iSort interface (ok, in ColdFusion this would be convention and not a requirement). The iSort interface would probably define a method to compare items of data from the Table. The Table would know how to use the Sorter’s interface and would sort the data accordingly.

Here’s a pseudo code example to illustrate this:

<!--- create a table that holds data --->
<cfset Table = CreateObject("Component", "model.table.Table").init(data) />
<!--- create an alphabetical sorter to sort the data --->
<cfset Sorter = CreateObject("Component", "model.sort.alphaSort").init("lastName", "ascending") />
<!--- pass the sorter into the table --->
<cfset Table.setSort(Sorter) />

As of now the Table’s data would be sorted how I’d like it to be.

filter(iFilter Filter) As with the sort method, this would receive a Filter object that implemented an interface that the Table knew how to use to filter the data. The iFilter interface would probably have a method that checked if an item of data matched the filter or not.

I start running into problems when I begin thinking about how to create visual representations of the data. In other words, how the heck to I translate the data in the component to HTML?

Well, you could, in theory, write a custom tag that knew the Table’s interface and could read data out of the Table and convert it into an HTML table. The problem is that this “breaks” encapsulation. If a component exposes its internal data to an external object such as a tag, then that data isn’t really encapsulated. You might as well store it in a structure. So, I don’t really like the idea of a tag.

I could also add a Render method to the Table component. Ideally this method would return the HTML to display the component. I’m not sure how I feel about this because it feels like the Table is beginning to take on too many responsibilities, but this is more of a gut feeling. It seems to beat passing the component into a tag.

The other nice thing about a render method on the table is that I could also add a print method that called the render method and then translated the resulting HTML into PDF or FlashPaper format.

So far, this seems like a reasonable solution. However, how do I sort and filter data once the Table is rendered to HTML and the HTML is displayed in the user’s browser?

The only answer I have to this question is that I cache the Table on the server and require the user to make a second trip (which I already don’t like) to the server which will then resort the cached Table. I don’t like this because it feels like I no longer have one component, but a set of related systems. I have the Table itself, but the Table has to know what events or pages to call on the server to get resorted. The Table has knowledge outside itself. Encapsulation is broken.

This is where I start to think about implementing the Table in JavaScript. I could implement the same API I described above in JavaScript. All, that is, except for print. I’ve been unable to think of a clean way to have a print method on a JavaScript Table object.

I suppose a print method could accept a URL and that the print method could get the Table’s rendered HTML and submit it to the provided URL which would be required to return the PDF or FlashPaper data.

After all this writing, I actually like that idea! It might seem weird that the JavaScript is making a call to the server, but it IS encapsulated. The JavaScript Table has no knowledge of anything outside itself. It simply knows that it submits data to a URL passed into the print method.

What do you think? How would you tackle something like this?

Comments on: "I'm Stumped" (13)

  1. Do you have the option of using Flex 2.0 or perhaps some ajax framework such as Adobe’s Spry? In Flex 2.0 you can create DataGrid objects that the user can sort and filter without having to go back to the server. Flex also has print capabilities. Spry also enables sorting and filtering without doing a page refresh.

    Otherwise I think you are going to create alot of code that others have already written either in Flex 2.0 or in JavaScript-ajax.

    Like

  2. Doug Hughes said:

    I guess I should have been explicit. I really would LOVE to use Flex 2. However, that’s just not in the budget.

    Now that I’ve said that, I do expect to use Spry for this system… but even then, I just wish I had one package I could wrap up and use. As it is, with Spry I’ll have to have a set of includes for the various scripts before I can use mine. I know I could wrap this up into a set of custom tags, but then creating the user interface for the filters becomes tricky (they can all have different interfaces, sadly).

    All in all, nothing I’ve thought of yet has smelled right. (Except Flex, that is.)

    Like

  3. Dan Sorensen said:

    Ray Camden has a set of custom tags he uses to do this sort of thing in Lighthouse Pro. It’s procedural and wasn’t designed to be used outside of that package, but it functions fairly well. It accepts a query and combines that with user input (filter params & column sort info) to display a nice sortable table. However, that’s not what you were asking.

    I agree that an HTML solution needs to be devised. There are too many times when Flex isn’t an option. Personally, I think you’re adding unnecessary complexity and server load by asking for dynamically generated PDF/Flash Paper based on the current query. I would advocate using a custom Print Style Sheet that eliminated unwanted info and presented the data in a pleasing format for paper. It would take some planning, but it’s workable and puts the load on the client.

    I’m slightly over my head here, but regarding the unwanted break in encapsulation, it might be best to break encapsulation with an API that would interface with a client tag/function specific to an output format. You could have the core function that would store the data and handle user input (filters/sorts), and then you could have a client, or plug-in function to render HTML, PDF/Flash Paper, XML, XLS, or other web services.

    That way, when a new method of outputting the data is desired one would just need to write a new output plugin. Example, Person A might prefer to display the data using table tags, whereas Person B might want to try a fancy DIV tag layout, and Person C wants to output XML.

    Just my .02

    Like

  4. I assume by “not in the budget” you are referring to Flex Data Services. Why not use the free SDK with simple HTTP requests instead?

    Like

  5. Doug Hughes said:

    Hans – There’s multiple ways to look at “not in the budget”. Really, they don’t want to pay for my time to use the free SDK (nor for Flex builder). Also, the PCs the app will be running on will be running a modern browser, but they had issues previously with Flash on the client PCs being able to support Flash Video. For this reason requiring (and supporting) the latest version of the Flash Player is too expensive.

    Like

  6. Hi Doug,

    Keep an eye on my blog over next few weeks as I have worked up a generic approach to solving these problems as part of LightBase using UI components and certain controller and model conventions. I have the architecture figured, but don’t want to post too much until I have a chance to play with the (fairly simple) code and check everything out. If you want to email me offline about any specifics, feel free.

    Like

  7. Doug ,I might be missing the point, but could you not use something like JSON to “render” the table data out to the client, you can then use client tools to sort and filter. These filters you store on the client as JS objects, that you can then send (as JSON objects again) and render it as a PDF, so, when you have a request to print a table as PDF you would send (from the client):
    Original table (in JSON format)
    Filter JSON object
    Sort JSON object

    you would then instantiate another table object (stateless right?) with this data, filters and sorters and do whatever you want for the PDF

    Make sense?

    Like

  8. Doug Hughes said:

    Mark – To be totally honest, I don’t know much about JSON. I know enough to say that what you’re suggesting sounds logical. I’ll look into it further when I reach that point. Thanks.

    Like

  9. Doug

    JSon has a couple of functions for CF that serialise CFObjects into a Json object (its like, really simple xml, but it evals straight to a JS object)

    This would mean that you would set up in Java Script a Table object, a sort and a filter object.

    You would have to kind of replicate this on the client side with your sorting and filteing (lots of articles on this all the way round) and when a client has finished modifying their sort and filter, then you save those objects back into a form (json js library) and then post those back and create the stuff.

    Contact me off list and I can help you out with some of this…

    (gmail same as email ehre)

    Like

  10. http://dotnet.org.za/members/glucophage-pi.aspx glucophage pi | glucophage pi
    http://dotnet.org.za/members/methotrexate-use-in-placenta-accreta.aspx methotrexate use in placenta accreta | methotrexate use in placenta accreta
    http://dotnet.org.za/members/3600mg-of-neurontin-a-day.aspx 3600mg of neurontin a day | 3600mg of neurontin a day
    http://dotnet.org.za/members/augmentin-and-alcohol-use.aspx augmentin and alcohol use | augmentin and alcohol use
    http://dotnet.org.za/members/z-pack-and-erythromycin-allergy.aspx z pack and erythromycin allergy | z pack and erythromycin allergy
    http://dotnet.org.za/members/erosive-gastritis-and-methotrexate.aspx erosive gastritis and methotrexate | erosive gastritis and methotrexate
    http://dotnet.org.za/members/levaquin-caused-digestive-illness.aspx levaquin caused digestive illness | levaquin caused digestive illness
    http://dotnet.org.za/members/can-i-give-motrin-and-dimetapp-to-my-teen.aspx can i give motrin and dimetapp to my teen | can i give motrin and dimetapp to my teen
    http://dotnet.org.za/members/how-to-snort-lidocaine.aspx how to snort lidocaine | how to snort lidocaine
    http://dotnet.org.za/members/fosamax-jaw.aspx fosamax jaw | fosamax jaw
    http://dotnet.org.za/members/long-term-usage-omeprazole.aspx long term usage omeprazole | long term usage omeprazole
    http://dotnet.org.za/members/substitutes-for-fosamax.aspx substitutes for fosamax | substitutes for fosamax
    http://dotnet.org.za/members/januvia-pros-and-cons.aspx januvia pros and cons | januvia pros and cons
    http://dotnet.org.za/members/fosamax-and-low-velocity-long-bone-fractures.aspx fosamax and low velocity long bone fractures | fosamax and low velocity long bone fractures
    http://dotnet.org.za/members/what-is-omeprazole-used-for.aspx what is omeprazole used for | what is omeprazole used for
    http://dotnet.org.za/members/avandia-crushed-rogaine.aspx avandia crushed rogaine | avandia crushed rogaine
    http://dotnet.org.za/members/erythromycin-antibiotic.aspx erythromycin antibiotic | erythromycin antibiotic
    http://dotnet.org.za/members/namenda-and-strokes.aspx namenda and strokes | namenda and strokes
    http://dotnet.org.za/members/medrol-pills-and-thrush.aspx medrol pills and thrush | medrol pills and thrush
    http://dotnet.org.za/members/methotrexate-and-folic-acid.aspx methotrexate and folic acid | methotrexate and folic acid
    http://dotnet.org.za/members/20-mg-omeprazole-delayed-release-100-tablets.aspx 20 mg omeprazole delayed release 100 tablets | 20 mg omeprazole delayed release 100 tablets
    http://dotnet.org.za/members/side-effects-namenda-combination-aricept.aspx side effects namenda combination aricept | side effects namenda combination aricept
    http://dotnet.org.za/members/best-time-to-dose-aricept.aspx best time to dose aricept | best time to dose aricept
    http://dotnet.org.za/members/levaquin-side-effects.aspx levaquin side effects | levaquin side effects
    http://dotnet.org.za/members/solu-medrol-msds.aspx solu medrol msds | solu medrol msds
    http://dotnet.org.za/members/neurontin-medication.aspx neurontin medication | neurontin medication
    http://dotnet.org.za/members/erythromycin-hydrochloride-msds.aspx erythromycin hydrochloride msds | erythromycin hydrochloride msds
    http://dotnet.org.za/members/motrin-to-stop-bleeding.aspx motrin to stop bleeding | motrin to stop bleeding
    http://dotnet.org.za/members/aricept-for-mini-stroke.aspx aricept for mini stroke | aricept for mini stroke
    http://dotnet.org.za/members/can-you-take-motrin-if-getting-bloodwork-done.aspx can you take motrin if getting bloodwork done | can you take motrin if getting bloodwork done

    Like

  11. http://dotnet.org.za/members/benzocaine-vs-lidocaine-for-pain.aspx benzocaine vs lidocaine for pain | benzocaine vs lidocaine for pain
    http://dotnet.org.za/members/neurontin-300mg.aspx neurontin 300mg | neurontin 300mg
    http://dotnet.org.za/members/can-tramadol-and-motrin-be-taken-together.aspx can tramadol and motrin be taken together | can tramadol and motrin be taken together
    http://dotnet.org.za/members/avelox-and-alcohol.aspx avelox and alcohol | avelox and alcohol
    http://dotnet.org.za/members/present-information-about-fosamax-google.aspx present information about fosamax google | present information about fosamax google
    http://dotnet.org.za/members/augmentin-alcohol.aspx augmentin alcohol | augmentin alcohol
    http://dotnet.org.za/members/naltrexone-prices.aspx naltrexone prices | naltrexone prices
    http://dotnet.org.za/members/levaquin-500-mg.aspx levaquin 500 mg | levaquin 500 mg
    http://dotnet.org.za/members/side-effects-of-depo-medrol-for-dogs.aspx side effects of depo medrol for dogs | side effects of depo medrol for dogs
    http://dotnet.org.za/members/aricept-stopping-how-too.aspx aricept stopping how too | aricept stopping how too
    http://dotnet.org.za/members/naltrexone-or-campral.aspx naltrexone or campral | naltrexone or campral
    http://dotnet.org.za/members/penile-clamp-lidocaine.aspx penile clamp lidocaine | penile clamp lidocaine
    http://dotnet.org.za/members/januvia-side-effects.aspx januvia side effects | januvia side effects
    http://dotnet.org.za/members/reports-in-europe-of-januvia-use-with-insulin.aspx reports in europe of januvia use with insulin | reports in europe of januvia use with insulin
    http://dotnet.org.za/members/stepped-on-nail-augmentin.aspx stepped on nail augmentin | stepped on nail augmentin
    http://dotnet.org.za/members/fosamax-and-atrial-fibrillation.aspx fosamax and atrial fibrillation | fosamax and atrial fibrillation
    http://dotnet.org.za/members/motrin-treatment-for-bed-wetting.aspx motrin treatment for bed wetting | motrin treatment for bed wetting
    http://dotnet.org.za/members/neurontin-for-hot-flashes.aspx neurontin for hot flashes | neurontin for hot flashes
    http://dotnet.org.za/members/methotrexate-toxicity.aspx methotrexate toxicity | methotrexate toxicity
    http://dotnet.org.za/members/ok-to-take-motrin-if-having-chest-pains.aspx ok to take motrin if having chest pains | ok to take motrin if having chest pains
    http://dotnet.org.za/members/naltrexone-ucla.aspx naltrexone ucla | naltrexone ucla
    http://dotnet.org.za/members/neurontin-for-the-treatment-of-epidural-fibrosis.aspx neurontin for the treatment of epidural fibrosis | neurontin for the treatment of epidural fibrosis
    http://dotnet.org.za/members/medrol.aspx medrol | medrol
    http://dotnet.org.za/members/gf-augmentin.aspx gf augmentin | gf augmentin
    http://dotnet.org.za/members/dental-work-methotrexate.aspx dental work methotrexate | dental work methotrexate
    http://dotnet.org.za/members/lidocaine-ointment.aspx lidocaine ointment | lidocaine ointment
    http://dotnet.org.za/members/motrin-active-ingredient.aspx motrin active ingredient | motrin active ingredient
    http://dotnet.org.za/members/alzheimers-namenda-adverse.aspx alzheimers namenda adverse | alzheimers namenda adverse
    http://dotnet.org.za/members/pinpoint-pupils-neurontin-methadone.aspx pinpoint pupils neurontin methadone | pinpoint pupils neurontin methadone
    http://dotnet.org.za/members/how-long-does-glucophage-stay-in-system.aspx how long does glucophage stay in system | how long does glucophage stay in system

    Like

  12. http://dotnet.org.za/members/20-mg-omeprazole-delayed-release-cheap.aspx 20 mg omeprazole delayed release cheap | 20 mg omeprazole delayed release cheap
    http://dotnet.org.za/members/is-glyformin-the-same-as-glucophage.aspx is glyformin the same as glucophage | is glyformin the same as glucophage
    http://dotnet.org.za/members/is-it-ok-to-drink-alcohol-while-taking-levaquin.aspx is it ok to drink alcohol while taking levaquin | is it ok to drink alcohol while taking levaquin
    http://dotnet.org.za/members/acid-reflux-omeprazole.aspx acid reflux omeprazole | acid reflux omeprazole
    http://dotnet.org.za/members/which-glucosamine-chondroitin-is-the-best.aspx which glucosamine chondroitin is the best | which glucosamine chondroitin is the best
    http://dotnet.org.za/members/geoda-software.aspx geoda software | geoda software
    http://dotnet.org.za/members/generic-neurontin-watson.aspx generic neurontin watson | generic neurontin watson
    http://dotnet.org.za/members/how-to-make-omeprazole-suspension.aspx how to make omeprazole suspension | how to make omeprazole suspension
    http://dotnet.org.za/members/fish-antibiotic-_2600_-erythromycin.aspx fish antibiotic & erythromycin | fish antibiotic & erythromycin
    http://dotnet.org.za/members/wats-up-with-the-drug-avandia.aspx wats up with the drug avandia | wats up with the drug avandia
    http://dotnet.org.za/members/avelox-price.aspx avelox price | avelox price
    http://dotnet.org.za/members/methotrexate-dosage.aspx methotrexate dosage | methotrexate dosage
    http://dotnet.org.za/members/namenda-discussions.aspx namenda discussions | namenda discussions
    http://dotnet.org.za/members/januvia-_2600_-drop-in-blood-pressure.aspx januvia & drop in blood pressure | januvia & drop in blood pressure
    http://dotnet.org.za/members/levaquin-toxicity-and-bowel-function.aspx levaquin toxicity and bowel function | levaquin toxicity and bowel function
    http://dotnet.org.za/members/motrin-liquigel.aspx motrin liquigel | motrin liquigel
    http://dotnet.org.za/members/aricept-maximum-dose.aspx aricept maximum dose | aricept maximum dose
    http://dotnet.org.za/members/avelox-400mg.aspx avelox 400mg | avelox 400mg
    http://dotnet.org.za/members/avandia-attorneys-lexington.aspx avandia attorneys lexington | avandia attorneys lexington
    http://dotnet.org.za/members/can-i-given-neurontin-to-my-beagle.aspx can i given neurontin to my beagle | can i given neurontin to my beagle
    http://dotnet.org.za/members/methotrexate-and-celebrex.aspx methotrexate and celebrex | methotrexate and celebrex
    http://dotnet.org.za/members/toprol-xl-dosage-side-effects-fosamax.aspx toprol xl dosage side effects fosamax | toprol xl dosage side effects fosamax
    http://dotnet.org.za/members/clindamycin-versus-erythromycin.aspx clindamycin versus erythromycin | clindamycin versus erythromycin
    http://dotnet.org.za/members/apo-omeprazole-and-alcohol.aspx apo omeprazole and alcohol | apo omeprazole and alcohol

    Like

  13. http://dotnet.org.za/members/motrin-and-bone-healing.aspx motrin and bone healing | motrin and bone healing
    http://dotnet.org.za/members/prednisone-versus-medrol-for-poison-ivy.aspx prednisone versus medrol for poison ivy | prednisone versus medrol for poison ivy
    http://dotnet.org.za/members/cortisone-and-lidocaine-ointment.aspx cortisone and lidocaine ointment | cortisone and lidocaine ointment
    http://dotnet.org.za/members/how-does-erythromycin-work.aspx how does erythromycin work | how does erythromycin work
    http://dotnet.org.za/members/geodon-80-mg.aspx geodon 80 mg | geodon 80 mg
    http://dotnet.org.za/members/can-you-drink-alcohol-and-take-levaquin.aspx can you drink alcohol and take levaquin | can you drink alcohol and take levaquin
    http://dotnet.org.za/members/motrin-before-oral-surgery.aspx motrin before oral surgery | motrin before oral surgery
    http://dotnet.org.za/members/depo-medrol-generic.aspx depo medrol generic | depo medrol generic
    http://dotnet.org.za/members/motrin-advil.aspx motrin advil | motrin advil
    http://dotnet.org.za/members/folic-acid-with-methotrexate-in-psoriasis.aspx folic acid with methotrexate in psoriasis | folic acid with methotrexate in psoriasis
    http://dotnet.org.za/members/is-neurontin-used-to-treat-neuropathy.aspx is neurontin used to treat neuropathy | is neurontin used to treat neuropathy
    http://dotnet.org.za/members/avandia-lawyers-sc.aspx avandia lawyers sc | avandia lawyers sc
    http://dotnet.org.za/members/depo-medrol-for-sneezing-cats.aspx depo medrol for sneezing cats | depo medrol for sneezing cats
    http://dotnet.org.za/members/low-cost-naltrexone.aspx low cost naltrexone | low cost naltrexone
    http://dotnet.org.za/members/erythromycin-dental-abscess.aspx erythromycin dental abscess | erythromycin dental abscess
    http://dotnet.org.za/members/lumigan-eye-closes.aspx lumigan eye closes | lumigan eye closes

    Like

Comments are closed.

Tag Cloud