lemon

Generating HTML output through a ColdFusion Component

I’ve been wrestling with a legacy application that I’ve inherited over the last month or so, and the more I look into it the more things I find that make me cringe.

The most frustrating of all is the fact that numerous CFCs are being used across the site to generate HTML output and content for the site. I’m not just talking a small link here or there, rather complete HTML tables, divs and everything else in between. One method I’m currently having to work with is almost 300 lines long and creates a full page worth of content to be output directly into the calling .cfm template. I’m not even going to mention the fact that these CFCs also call and reference the Application, Request and Session scopes (although I just did). Encapsulation, anyone?

I know my thoughts on generating such things using CFCs, but I wanted to open it up and see what you think. Should CFCs be used to create and output HTML? If so, how much? Should you be ok with creating links and small snippets, or do you think it’s ok to create large chunks of HTML?

The floor is yours.. hit me with your nuggets of wisdom and opinion.

32 Comments

Leave a Comment
  1. I think it’s OK to output HTML in case of ajax-calls or maybe generating emails. If it stays in cfml (includes/cfc-calls) all my html should be in .cfm files. But that’s in a perfect world, when working in a legacy app (especially one from before App.cfc) things become a lot messier.

  2. I am assuming that by ‘generating HTML’ you mean that the ‘output’ attribute is set to ‘true’. If that is the case, I feel for you.

    I have no issue with creating methods in a CFC that generate HTML, but return that HTML as a string – but simply outputting HTML inside the method is juts….ew.

    The cool thing is, there is an easy fix – simply return the generated output as a string and wrap the method calls in tags. :D

  3. Maybe it depends on your thinking of the use of the particular CFC. It could be that it’s sole purpose is to output some chunk of html, and then it makes sense.

    For instance I have a cms with a skin.cfc file which gets piped all the components of a page for output (usually from a url re-writing template). The cfc also incorporates plugins, etc. It even calls other CFCs for the header and footer display (a great trick when using wordpress but want to keep the header and footer menus dynamic).

    However if you’re using a CFC purely for some server-side data crunching then I’d leave display out of it. The CFC should probably just return a result to the calling template.

    So I think it’s OK depending on the usage.

  4. This is partially off-topic, but I’ve been wrestling with how to call a CFC method in a jQuery Ajax() call and get the request scope injected at the same time. I’ve had good success with injecting the outside scopes in the .init(), but that doesn’t seem to be possible when calling a remote method directly.

    Any suggestions (so this code doesn’t become THAT legacy code)?

  5. @Jules – In my opinion, it is never acceptable to output HTML inside a CFC method.

    Generate HTML? Fine, just return the string, but I think it is a huge ‘no no’ to have the generated HTML get displayed from inside the method.

    I just cannot see a valid use case for doing that, not when it’s just as easy to generate the string (using cfsavecontent ) and simply return it from the method call.

    1. I don’t have any formal training for CFCs (and CF in general). Is keeping all display out of a CFC a philosophy or is that a soft rule from Adobe?
      The way I see it is, if you are generating html from a CFC, why not let it output at html? It seems like to me that wrapping it all in a cfsavecontent, returning that variable, then outputting it would be a bunch of overhead as well as unnecessary code.
      What about using (or thinking) of CFCs as includes or custom tags?

      1. In my opinion, it is poor practice. Using cfsavecontent to create the string and then return it is not adding a lot of overhead, if any.

        Some (myself included) might argue that it breaks encapsulation

        Personally, for generating output, I prefer custom tags, though I have used CFC methods to generate HTML and return the string.

    2. I agree.. HTML and content elements should never be rendered from a CFC. Period. The great thing about CFCs is the fact you _can_ do that (as you can also do pretty much everything) but you instantly lose any encapsulation, control and management.

      This particular method is one of hundreds spanning 50+ components. It’s a heady mix of query components, dsp components (with the HTML output) and some form of service layers. I really wish I could post it or show some of it, but alas.

      This is a clear case for why MVC-based apps (of any scale using any framework) are crucially important for creating clear, concise systems.

    3. I guess I don’t understand the difference…

      [cffunction name='sample']
      (some cf processing here)
      [div]
      some html content
      [/div]
      [/cffunction]

      – vs –

      [cffunction name='sample']
      (some cf processing here)
      [cfsavecontent variable='sampleString']
      [div]
      some html content
      [/div]
      [/cfsavecontent]
      [cfreturn expr='#sampleString#']
      [/cffunction]

      Wouldn’t either be called with: [cfoutput]#application.yourcfc.sample()#[/cfoutput] ?

      I guess the real pure code is to keep all html out of CFCs altogether, making the above comparison moot.

      1. The difference is, the HTML is not just generated, but rendered inside the CFC in your first example…this is NOT a good practice.

        You want your CFC methods to only take arguments and return data…nothing else – though, frequently, there is no need to return anything. By rendering output in a CFC method, you ‘break’ that ‘rule’.

        Can you do it? Yep. Should you do it? Nope.

        Again, I would typically use s custom tag for output, but have

  6. I think this is a great point for discussion. I sometimes (but, rarely) use CFCs to generate HTML content. I am currently working on a project where I do this because the HTML content relies on data in the CFC AND is going to be used by more than one CFM template file (code reuse).

    For instance, I have a CFC for a “Document Builder”. The Document Builder starts with one of many base/template documents. Each document has a unique set of parameters that can be set to update the document – think PDF Form. So, an HTML form is generated by the CFC and output in the front-end template CFM file. The HTML form is generated by parsing form names and configuration settings (is it a text field?, what is the max length?, what validation is necessary?, etc.). This same data is used by the CFC when it captures the form post, validates the values entered, and updates the Document for the user to see their entries in the document.

    This HTML form is also used in another CFM template file where users upload new documents and test them to be sure the generated HTML form will work.

    I guess I could port the HTML form generation to a custom tag, but, then I’d need to manage sending all the data to and from one more place – why not just keep it all in the CFC and use the THIS and VARIABLES scopes with ease? We (CF developers in general, that is) use CFCs to generate JSON strings in AJAX requests, don’t we? Why not HTML that’s going to be re-used and uses data already in the CFC?

    1. I am not saying there is anything wrong with generating HTML in a CFC – as long as you return the HTML string from that method and not render the HTML directly (by using output=’true’ and cfoutput) inside the method.

      This is bad practice, will lead to messy HTML and likely be a bear to troubleshoot down the road.

      When we generate JSON strings in AJAX requests, we are returning the JSON from the method call, not rendering the output directly within the CFC.

  7. I’ve actually been doing the exact same thing all day!
    5 odd functions all with output=”true”, decided to re-write them all and use the cfsavecontent way, not only is it better for encapsulation, it also seems to create ‘cleaner’ code, eliminates lots of whitespace and makes it easy to decipher between output code and processing code.

  8. I’ve got an application here which generates (not renders) HTML inside of CFCs, in this instance for Email content, and it has always made me feel uncomfortable, I think primarily because it’s so bloody verbose.

    My preferred method is to keep this content in a separate location, under the views, with a renderer class which renders the content if I need to access it within the model, for emails, or even ajax calls I suppose.

    My view is that anything that determines the way the content appears to the user, should be kept within the view layer.

    1. “anything that determines the way the content appears to the user, should be kept within the view layer.”

      could not agree more.

      1. But do you always want the view to have a ton of ColdFusion code necessary in order to properly output the view? This doesn’t comply with “keep business rules out of the view”. That’s the stand I take – if it’s a business rule, it should be in the CFC. I’m not talking about outputting entire pages from a CFC, just portions of pages, as needed.

        1. Again..if you want to generate the HTML in a CFC, and return the string from the method, that is fine, but, as soon as you set output=”true” and start using cfoutput inside the CFC method to actually render the output, you have crossed a line that ought not be crossed.

          It is bad practice. It can lead to sloppy HTML. It can be a bitch to troubleshoot.

          Just because you can do something, does not mean that you should.

          1. Thanks Scott. I got your message. I’m not talking about outputting directly from CFCs.

        2. In response to your question: Yes. I want my view to have any and all code that is necessary in order to properly output the view.

          I think what you might be calling ‘business rules’ that would be in the view are what I like to call ‘view logic’. This would be code that would determine if, for example, a delete button should be displayed given a certain user type. Yes, it is a ‘business rule’, but it is also a ‘view rule’.

          If you need to process ‘views’ in your CFCs to meet certain business rules, I might argue that your architecture is not optimal.

      1. I suppose that is the core crux of the question.. should we as developers get ourselves into the position where we need to rely on HTML output through CFCs? Can it be averted by structuring an application differently? Can the requirement to render HTML in such a way be bypassed at the root level when building the app?

        1. I think it is a good idea to strive for this, but, ultimately, it depends on the situation.

          I have had times where generating (but never, ever rendering) HTML in a CFC was the best solution. I think a great example is a CFC whose purpose is to generate and send emails. Yes, I guess it is technically a ‘view’, but it is, in my opinion, different, and can be treated differently.

          I think its ‘dirtier’ to call custom tags or have includes to ‘view’ files, that generate email messages than it is to generate said messages inside s CFC method.

  9. For me it depends on the purpose of the cfc. i have different rules for the service layer than the controller layer. in my controllers, i allow direct calls to the application and session scopes. i generally keep html rendering in the view, but if i need the service layer to control some html i’ll include a view cfm file surrounded by cfsavecontent.

  10. I look at CFC’s as returning data. Returning a block of HTML can be construed as returning ‘data’, but not outputting that in the CFC itself.

    If I make an Ajax call that expects a block of HTML, chances are that call is directly to a .cfm template itself. I can see people using CFC’s as custom tags, but CF already has a custom tag syntax that is fairly encapsulated and robust.

  11. I thought I’d chime in with just an extra little bit of info in regards the code Matt is on about.

    The CFCs aren’t building the HTML and wrapping it with …. the HTML is being built line by line using something similar to the following:

    var html = “”;
    html = html & “Content here”;
    html = html & “”;
    return html;

  12. here’s an alternative to using output=”true” in your CFC’s and functions. Instead of outputting it directly to the browser, encapsulate the html output in a cfsavecontent and return that to the calling page as a string. It has none of the drawbacks of suing output=”true” and still allows you to use html in a function.

    regards,
    larry

  13. I forgot to add that by using CFSavecontent you also get the additional advantage of being able to further manipulate the content before displaying the output.

  14. I’m just wondering, is savecontent necessary all the time? If there anything wrong with just returning a string without it?

    I have something like this included file helper file that returns a string, call from the view:

    if (arguments.postTypeId == 1) {
    return “div title=’question asked on etc…’ & #arguments.title# & ‘/div’”;
    } else {
    return “div title=’answered on etc…’ & #arguments.title# & ‘/div’”;
    }

    Note I omitted the html brackets…

  15. Using cfsavecontent isn’t necessary. I find it a cleaner way of generating string variables, easier to read and easier to debug when there’s an issue.

  16. Hello – interesting debate here.
    I’m pretty new at CFCs but I started a while back and I DO use a CFC to generate output with divs.
    I do a bunch of logic inside the CFC and then compile the elements (which changes based on passed arguments)
    The .cfm page has only one var for the output of the CFC.
    I have 50+ sites using that one bit of code and it’s allowed me to get control as I know exactly the output and the names of the divs.
    I then control the look and feel via CSS – standard sites use a shared .CSS file – whereas custom sites either have CSS over-writes or their own complete CSS file.
    I have at times thought I should output a query and format on the .cfm page – but what’s really the difference? Not sure why this is “bad practice”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>