Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsGeneralPHPASPPerlColdFusionFlashHTML, CSS, ScriptsBrowsers

Webmaster Forum / ColdFusion / Advanced Techniques / August 2007



Tip: Looking for answers? Try searching our database.

dynamic return from a function based on an argument

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
sjlsam2 - 28 Aug 2007 18:50 GMT
I have a function that I am using to output a nested list of child/parent
relationships

the function works wonderfully except that i want to be able to change the way
the list is displayed depending on an argument being passed

i want the list to be displayed twice on the same page, one with output in a
table, and one with output in a drop down box
i thought the easiest way would be to create an argument that can be used in
IF statements

[b]look at my code below[/b]

[Q]<!--- establish default values --->
<cfparam name="output" default="">
<cfparam name="catNameOutput" default="">
<cfparam name="indent" default="">

<cffunction name="GenerateCategories" access="public" returntype="string">
  <!--- this holds the outermost parent value being passed to the function --->
  <cfargument name="GenCatParent" type="uuid" required="yes" default=0 >
 
  <!--- this holds the nested level we are on --->
  <cfargument name="level" type="numeric" required="yes" default=0 >
 
  <!--- this holds the output_type we need for display purposes --->
  <cfargument name="output_type" type="numeric" required="yes" default=0 >
 
  <!--- grab the children of the received category --->
  <cfquery name="rsCategoryChildren" datasource="webdsn">
  SELECT * FROM dbo.BlogCategories
  WHERE catParent = '#GenCatParent#'
  ORDER BY catName ASC
  </cfquery>
  <cfloop query="rsCategoryChildren">
    <!--- keep track of the indentation needed depending on which level we are
at --->
    <cfloop from="0" to="#arguments.level#" index="i">
      <cfset indent = indent & "&nbsp;&nbsp;">
    </cfloop>
   
    <!--- if the nest is being used in the dropdown on the category manage page,
we need to use option tags --->
    <cfif arguments.output_type EQ 1>
        <cfset catNameOutput = "<option value='" & catPK & "'>" & indent &
Trim(catName) & "</option>">
    </cfif>
   
    <!--- if the nest is being used in the table on the category manage page, we
need to use table row tags --->
    <cfif arguments.output_type EQ 2>
        <cfset catNameOutput = "<tr> <td>edit</td> <td>delete</td> <td>" & indent &
Trim(catName) & "</td> </tr>">
    </cfif>
   
    <cfset output = output & catNameOutput>
   
    <!--- reset the indentation --->
    <cfset indent = "">
   
    <!--- check for children of this child --->
    <cfquery name="checkForKids" datasource="webdsn">
    SELECT * FROM dbo.BlogCategories
    WHERE catParent = '#rsCategoryChildren.catPK#'
    ORDER BY catName ASC
    </cfquery>
    <!--- if there are any, call this function recursively --->
    <cfif checkForKids.recordcount GT 0>
      <cfset GenerateCategories(genCatParent=catPK, level = level +1,
output_type = arguments.output_type)>
    </cfif>
  </cfloop>
 
  <cfreturn output>
 
</cffunction>

<cfquery name="rsCategoryParents" datasource="webdsn">
    SELECT * FROM dbo.BlogCategories
    WHERE catParent IS NULL
    ORDER BY catName ASC
</cfquery>
[/Q]

[b]and here is how i am calling the function for each situation (the table and
the dropdown):[/b]

[Q]
<table width="100%" class="managementtable">
  <tr bgcolor="#F6F6F6">
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>Category Name</td>
  </tr>
 
    <cfloop query="rsCategoryParents">
     <cfoutput><tr> <td>edit</td> <td>delete</td> <td>#Trim(catName)#</td>
</tr></cfoutput>
     <cfset recursivecats =
GenerateCategories(genCatParent=catPK,level=0,output_type=2)>
     <cfoutput>#recursivecats#</cfoutput>
    </cfloop>
 
</table>
<!---------------------------------------------------------------------------->
    <select name="select">
        <option>None</option>
       
        <cfoutput query="rsCategoryParents">
         <option value="#catPK#">#Trim(catName)#</option>
         <cfset recursivecats =
GenerateCategories(genCatParent=catPK,level=0,output_type=1)>
         #recursivecats#
        </cfoutput>

          </select>
[/Q]

calling the function for the table and the dropdown on the same page does not
work
if the function is first called with the argument for table, it tries to also
output the table formatted code when the function is called again (even if it
is called again with the argument for dropdown)

is there another way i can have the same function output two different sets of
data based on an argument?  what am i doing wrong

thanks for your time
nummsa - 28 Aug 2007 18:54 GMT
Check out the returntype="any" attribute in the CFFUNCTION tag.

I would recommend against using this because I'm more of a proponent of "scrict typing", but coldfusion allows it.
sjlsam2 - 28 Aug 2007 19:18 GMT
hello, thanks for the fast reply
but the returntype is not my issue

the variable being returned is called output
output is set to different strings as a result of an argument being 1 or 2

for some reason, whenever i call the function on a page twice, output gets set
to whatever the first argument is, that is being requested

for example

<function name='test'>
<if type = 1><set output = "Joe"></if>
<if type = 2><set output = "Bob"></if>
<return output>
</function>

Now I call the function twice on the same page:
test(type=1)
<br />
test(type=2)

The output SHOULD look like this:
Joe
Bob

Instead the output comes out looking like this:
Joe
Joe

The IF statements are done correctly, and the function is receiving the
argument correctly, but my dynamic output is not working

my full code of the function is in the first post
nummsa - 28 Aug 2007 21:24 GMT
Try getting rid of the cfparam name="output" line. It seems the scope of this
variable is getting lost so that every instance of the ouput variable is global
possible. I've found a few scope problems in the past.
In your cffunction where it's doing the cfset on the output variable, do a
debugging cfoutput or cfdump to show that the cfif logic is working correctly.
Even try outputing the output variable at that time after you set it to make
sure it's alright then also dump the output variable as it's returned from the
function.
sjlsam2 - 29 Aug 2007 21:30 GMT
i was able to fix my problem by creating a different cfreturn based on the argument
cf_dev2 - 29 Aug 2007 22:07 GMT
I didn't read the code thoroughly, but personally I wouldn't mix the db and
html code that way.  IMO it complicates the code and makes it harder to follow.
 But whatever option you choose, you should always VAR variables that are only
used inside a function.  When you don't use "var" unscoped variables are placed
in the shared VARIABLES scope, which is likely to cause more scope problems in
the future.
Swift - 29 Aug 2007 23:12 GMT
sjlsam2,

Yeah, I think the main problem you had was a scoping one. For the second
function call, the output variable already contained all of the output code
from the first function call. In fact, I wouldn't be surprised to find that the
output string for the second function call contained the output of the first
plus the output of the second, and that it didn't render correctly on screen. A
[i]View Source[/i] would have determined that.

Anyhow, I suggest that you VAR your output variable as cf_dev2 suggests, and
delete the three CFParam lines at the top. Further, your recursive call would
therefore need to return it's result to the output variable, thus completing
the recursive loop. See below:

...
<!--- this holds the output_type we need for display purposes --->
<cfargument name="output_type" type="numeric" required="yes" default=0 >

[b]<CFSet Var Output = "">[/b]
[b]<CFSet Var catNameOutput = "">[/b]
[b]<CFSet Var indent= RepeatString("&nbsp;&nbsp;", Arguments.Level)>[/b]

<!--- grab the children of the received category --->
<cfquery name="rsCategoryChildren" datasource="webdsn">
SELECT * FROM dbo.BlogCategories
...

and

...
<!--- if there are any, call this function recursively --->
<cfif checkForKids.recordcount GT 0>
<cfset [b]Output = Output & [/b]GenerateCategories(genCatParent=catPK, level =
level +1, output_type = arguments.output_type)>
</cfif>
</cfloop>

This is what I suggest with your code. HTH :)
Swift
cf_dev2 - 30 Aug 2007 03:05 GMT
>Further, your recursive call would therefore need to return it's result to the output >variable, thus completing the recursive loop.

Good point.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.