Search code examples
ajaxcoldfusionfw1

Using only a controller in FW1 without a view


I have an Ajax request that sends some data to a page and expects back a truthy or falsey value depending on if the data was saved. In my controller I do everything and set the content to a true or false value. I really don't want to create a view just to output 1 variable, so I was wondering if there was a way that I don't have to use a view and only use the controller to output simple strings.


Solution

  • I believe you cannot disable views completely, but there's a pretty simple workaround: you can create one view and use it for many actions.

    Let's say we've created the view views/main/ajax.cfm, what could be inside it? Obviously, simplest way is:

    <cfoutput>#HTMLEditFormat(rc.response)#</cfoutput>
    

    Personally I like returning JSON, it allows me to have status field, plus data, if needed. This way my view looks like this:

    <cfheader name="Content-Type" value="application/json" />
    <cfoutput>#SerializeJSON(rc.response)#</cfoutput>
    

    Any way, now in our action we need to do something like this:

    // prevent displaying the layout
    request.layout = false;
    
    // force special view
    variables.fw.setView("main.ajax");
    
    // init response (according to the choice made earlier)
    rc.response["status"] = "OK";
    rc.response = "";
    

    There's one more gotcha for this. Sometimes you don't want AJAX page to be accessed directly (like opened in browser), or vise-versa -- want to do some debugging when it is.

    There's a cool helper isAjax in CFWheels framework, it is easy to port to the FW/1. It could be as simple as adding method like this to controller:

    /*
    * Check if request is performed via AJAX
    */
    private boolean function isAjax() {
    
        return (cgi.HTTP_X_REQUESTED_WITH EQ "XMLHTTPRequest");
    
    }
    

    Actually, that setup code above is also helper method in my apps:

    /*
    * Set up for AJAX response
    */
    private struct function setAjax() {
    
        // prevent displaying the layout
        request.layout = false;
    
        // force special view
        variables.fw.setView("main.ajax");
    
        local.response["status"] = "OK";
    
        return local.response;
    
    }
    

    So in my action code whole check looks like this, which is pretty compact and convenient:

    if (isAjax()) {
        rc.response = setAjax();
    }
    else {
        return showNotFound();
    }
    

    Hope this helps.