Showing posts with label Bind. Show all posts
Showing posts with label Bind. Show all posts

Thursday, January 19, 2012

dynamically get url or form parameters and set variables or query strings for cflayout calls, ajax binds, iframe or cfincludes, links or in-page use.

I have some 'main' pages which use cflayout to actually hold LOTS of pages. Some are content 'in' the main page inside the cflayout code and some are 'bound' within a cflayoutarea source or ajax call and some are 'cf includes'.

Some might even be a secondary situation, like an iframe inside a cfinclude inside a cflayoutarea bind which is inside the main page which had params passed to it from somewhere. Got all that?! Not saying I'm going to do that, but I might want to.

Because (thanks to cflayout) this holds what amounts to a whole website, directly or indirectly, all being called via the same page technically, it gets complicated.

There are three things I don't 'know' for this page. Partly because there are so many different files involved and calls to them coming from everywhere. Partly because I'm unlikely to remember later every possible detail in the whole site, which is what happens when you do hobby sites at 2am 'cause it ain't your real job. All these unknowns and possibilities need to be handled right up top, generically no matter what their situation, so it's simply all available to me in any form I need it later on in the page, and can even be applied to everything 'generically'.

That way, whatever it is that particular thing needs, will be included in there somewhere (and extra stuff is ignored by what we call).

Things I need to know:

Q: What parameters were passed when I loaded this page and what are their values?

Q: Did those parameters come a form or a url?

Q: Do those need to be written into an inpage var, or conjoined on a url-query string?

Bear in mind var names should be distinct in the site (so one thing coming in for page X, if applied to a query string for page Y, would not affect it), and that any bound/included/called pages using the vars we have here of course must use default cfparams and/or check for existence of their needed params.


<!--- get any and all parameters passed on the url --->
<cfset paramsurl = structKeyList(url)>

<!--- put a parameter in place in a new var, this will be ignored (like 1=1 in SQL) --->
<cfset paramsurllist = "x=0">

<!--- loop through the list of params --->
<cfloop index="ndx01" list="#paramsurl#">

<!-- see it for debug: <cfoutput><div>#ndx01# = #url[ndx01]#</div></cfoutput>-->

<!--- build the query string for use in links if needed --->
<cfset paramsurllist = '#variables.paramsurllist#' & '&#ndx01#=#url[ndx01]#'>

<!--- set the var for use in-page if needed --->
<cfset #ndx01# = "#url[ndx01]#">

</cfloop>

<!-- see it for debug: show me my query string <cfoutput>#paramsurllist#</cfoutput>-->


<!--- get any and all parameters passed on the form --->
<cfset paramsform = structKeyList(form)>

<!--- put a parameter in place in a new var, this will be ignored --->
<cfset paramsformlist = "x=0">

<!--- loop through the list of params --->
<cfloop index="ndx02" list="#paramsform#">

<!-- see it for debug: <cfoutput><div>#ndx02# = #form[ndx02]#</div></cfoutput> -->

<!--- build the query string for use in links if needed --->
<cfset paramsformlist = '#variables.paramsformlist#' & '&#ndx02#=#form[ndx02]#'>

<!--- set the var for use in-page if needed --->
<cfset #ndx02# = "#url[ndx02]#">

</cfloop>

<!-- see it for debug: show me my query string <cfoutput>#paramsformlist#</cfoutput> -->

<!--- now, work out generic all-inclusive string to add as needed to anything "pulled in" --->

<!--- if incoming url params existed --->
<cfif variables.paramsurllist is not 'x=0'>

<!--- make a generic caller param string from the url stuff. --->
<cfset addcallerparams = "#variables.paramsurllist#">

<!--- if instead any params came from a form --->
<cfelseif variables.paramsformlist is not 'x=0'>

<!--- make a generic caller param string from the form stuff. --->
<cfset addcallerparams = "#variables.paramsformlist#">

<!--- worst case just put our default param on there. --->
<cfelse><cfset addcallerparams = "x=0">
</cfif>

Now, every iframe, or cflayoutarea source, or other ajax bind, or a regular link, can simply have "?#variables.addcallerparams#" added to it.

<cfset mylink = "_2012a_daily.cfm?#variables.addcallerparams#">
(then use in context)

And in the cases when using that doesn't help at all, because passing these vars on a source parameter in cflayoutarea apparently doesn't work (you'd think they could mention that...), we already have the variables set in the page in that case. So any incoming content that is bound or cfinclude, will pick up the var's existence and value from there instead.

PJ

Sunday, August 3, 2008

CFGRID and CFC Binding How To

I avoided using a CFC binding initially because I didn't grok how and, before I knew that my route made pagination impossible, a query in the HTML CFGRID seemed so much easier. But here is how the binding part is done.

In the CFC file you're going to have the following:

1. A function name with arguments
2. Your query
3. Not always but in my case, a query return for the grid.

The function is going to have remote access and return a structure. Here is my code for it:


<cffunction name="comments" access="remote" returntype="struct">
<cfargument name="page" required="true">
<cfargument name="pageSize" required="true">
<cfargument name="gridsortcolumn" required="true">
<cfargument name="gridsortdirection" required="true">


Page means, "Do you want this to do paging, where things are broken into separate pages?" PageSize means, "How big (how many records) should each page be?" The sorts are fairly obvious I think...

If you have the above it means you will have to have the page and pageSize defined in your CFGRID tag in your CFM page, and you can control it from there. I did not define my grid sorts and it didn't break.

Next you have your query. Whatever query you were using to output records prior to CFGRID will probably work fine, but I ended up having to hack mine to do all kinds of stuff that CFGRID made a royal pain in the butt, so I fixed it through SQL instead of CFML. Will cover that in another post.

Then you have your query "return". You find this in documentation under functions, queryconvertforgrid function.

In my case it has three values:
1 - the name of my query
2 - page
3 - pagesize

And I mean those strings (page and pagesize) not true/numeric. Here's my code, where my query is called selectAll:


<cfreturn queryconvertforgrid(selectAll,page,pagesize)/>


Now to put the CFC together you'll want these three things in order. I have a file called getcomments.cfc and here is the code, with the query revised for public use of course. Note that the CFC did not find my datasource which is a variable set in my Application.cfm file, so I had to manually CFSET that value before running the query.


<cffunction name="comments" access="remote" returntype="struct">
<cfargument name="page" required="true">
<cfargument name="pageSize" required="true">
<cfargument name="gridsortcolumn" required="true">
<cfargument name="gridsortdirection" required="true">

<cfquery datasource="myds" name="selectAll" maxrows="1000">
My query goes here
</cfquery>

<cfreturn queryconvertforgrid(selectAll,page,pagesize)/>
</cffunction>


Then in my CFM file, my HTML format CFGRID used this code to call it:


<cfform name="myform" id="myformid">
<cfgrid
name = "myGrid"
format="html"
bindOnLoad="yes"
bind="cfc:getcomments.comments({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})"
pageSize="10"
preservePageOnSort="true"
selectMode="single"
selectOnLoad="no"
font="Verdana"
fontsize="11"
label="True"
stripeRows="true"
stripeRowColor="##D9CCFF"
selectColor="##994FE6"
>
<cfgridcolumn name="id" display="no" >
<cfgridcolumn name="DateEntered" display="yes" header="Date" mask="EEE DD-MMM-YY H:NN A">
<cfgridcolumn name="Alias" italic="yes" display="yes" header="From">
<cfgridcolumn name="See" width="35" display="yes" >
<cfgridcolumn name="theComment" fontsize="1.2em" textColor="##661A99" width="700" display="yes" header="Comment">
</cfgrid>
</cfform>


Notice that there is some styling in one of the columns and that works, and date formatting in the date column which did not work at all so I did something different, which I'll cover in another post. The 'see' value there is a big string from a special SQL call that gave me an HREF link, and an image, and appended the record ID, because stupid CFGRID wouldn't let me get rid of underlining every damn thing if I used the HREF attribute.

CGRID and Auto Pagination

Everyone raved about how cool it was that ColdFusion's CFGRID tag automatically would do the pagination for you.

All the little examples I looked at, had that nifty little page number and button at the bottom.

Except mine. I could do code pretty much just like the examples, except that I was using an HTML form and a QUERY in it, but the little pagination thing never appeared.

It turns out that you cannot do pagination in a QUERY HTML CFGRID in CF8. Instead, you have to put your query out in a CFC page and "bind" that to the CFGRID. It is the CFC page that actually works out the pagination stuff.

I'll cover the CFC and binding separately.