0

I have a .cfc file with all my functions in it (wrapped in a <cfcomponent> tag), including this one:

<cffunction name="getFooter" output="false" access="public" returnType="string">
  <cfargument name="showFooter" type="string" required="false" default="" />

  <cfreturn footer />
  <cfset application.lib.getFooter(arguments.footer)>
</cffunction>
<cfset footer = getFooter(footer="<footer class="text-center">I am a footer.</footer>") />

And in my .cfm file, I put:

<cfoutput>#footer#</cfoutput>

It is not displaying the footer.

When I have all of this in a single .cfm file, it works fine.

I need to be able to store the function in my .cfc file and call it from anywhere in the application.

What am I missing?

Millhorn
  • 2,953
  • 7
  • 39
  • 77
  • 1
    For your immediate problem, refer to BKBK's answer to your previous question. Also in your previous question you stated that you are new to ColdFusion. That is apparent from your question because you are doing a few things fundamentally wrong. I suggest learning the fundamentals of ColdFusion components so that your attempts to use them will go better than this one has so far. – Dan Bracuk Jul 24 '20 at 03:15
  • @DanBracuk - I was kind of thrown into this not realizing the learning curve. I'm a front-end developer by trade, and unfortunately, I have to learn as I go. In the above situation, you would go with BKBK's solution, but that solution isn't what I'm being asked to do. I'm being asked to write the function in a .cfc file and call it from anywhere in the application. Where am I going wrong with what you see above? – Millhorn Jul 24 '20 at 03:35
  • @DanBracuk To be quite honest, I'm having a hard time finding anything on "calling a function from a cfc file anywhere in an application". Otherwise, I'm sure I'd have the answers I'm looking for. – Millhorn Jul 24 '20 at 03:39
  • 1
    BKBK's answer to your other question satisfies your stated requirement of `write the function in a .cfc file and call it from anywhere in the application.`. Your objection was, 'Writing out the function is on thing, but if I'm going to write out everything you have in testPage.cfm in every file where I want to put the footer, I might as well just put the actual footer.'. Subsequently he commented out the `` tag so there is one fewer line. As far as the amount of code to call the function goes, that's how it works. You have to create an object first. – Dan Bracuk Jul 24 '20 at 12:21
  • @JaredNewman, your code contains mistakes. (1) the line`cfset footer = getFooter(footer="
    I am a footer.
    ") />` is in the pseudoconstructor (space between functions in a cfc). It shouldn't be there, unless you want to define it as a property of the CFC. Even then, only the CFC will have access to it. (2) the line `cfset footer = getFooter(footer="
    I am a footer.
    ") />` follows the return statement, and so is redundant. (3) You haven't escaped the quotes in the string `"
    I am a footer.
    "`.
    – BKBK Jul 24 '20 at 14:04

6 Answers6

1

You explain your requirement clearly:

I need to be able to...call it from anywhere in the application.

So, don't do this:

"have a .cfc file with all my functions in it (wrapped in a tag), including this one:"

The requirement, "call it from anywhere in the application", implies just one thing in ColdFusion: an application-scoped variable.

So, do the following instead: transfer the footer functionality from that CFC to your Application.cfc.

Let's assume the following is an excerpt of your Application.cfc.

Then, do something like:

<cfcomponent displayname="Application" output="true" hint="Handle the application.">

<!--- Set up the application. --->
<cfset this.Name = "AppCFC" />
<cfset this.ApplicationTimeout = createTimeSpan( 1, 0, 0, 0 ) />
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 30, 0 ) />
<cfset this.sessionManagement = true />

<cffunction
    name="OnApplicationStart"
    access="public"
    returntype="boolean"
    output="false"
    hint="Fires when the application is first created.">
    
    <!--- This variable is available to every CFM page in the application --->
    <cfset application.footer=getFooter()>
    
    <cfreturn true />
</cffunction>


<cffunction 
    name="getFooter" 
    output="false" 
    access="public" 
    returnType="string">
    
    <cfset var footer = "<footer class=""text-center"">I am a footer.</footer>" />

    <cfreturn footer />
</cffunction>

</cfcomponent>

Then, in any CFM file in the application:

<cfoutput>#application.footer#</cfoutput>
BKBK
  • 484
  • 2
  • 9
  • I do appreciate this, but we store all of our functions in a lib.cfc file. That's not scoped to the application scope anymore, so that doesn't work. I thought it might be locally scoped, but that's not working either. I know there's a fundamental concept I'm not understanding here, but I'm not sure what it is. – Millhorn Jul 24 '20 at 16:19
  • Yes, @JaredNewman, to borrow your own words, there are some fundamental concepts you're not understanding here. The concepts have in fact been mentioned. (1)The requirement, "call it from anywhere in the application", implies just one thing in ColdFusion: an application-scoped variable. [NOT "locally scoped"] So, do the following instead: transfer the footer functionality from that CFC to your Application.cfc. (2) Alternatively, you may choose to instantiate the Lib cfc in onApplicationStart. That's fine, too. I have now added this alternative answer. – BKBK Jul 26 '20 at 14:26
1

You stated, we store all of our functions in a lib.cfc file.. So, in that file, write your function.

<cffunction name = "writeAppABCFooter"  <!---descriptive name in case there is another footer --->
access = "public"
output = "yes" <!--- this is important --->
returntype = "void">
html code for footer
</cffunction>

To call your function, first create an object of lib.cfc.

<cfobject name = "FooterObject" component = "lib">

Then call the function.

<cfset FooterObject.writeAppABCFooter()>

This assumes that lib.cfc exists in a location that enables it to be called by any application.

Dan Bracuk
  • 20,699
  • 4
  • 26
  • 43
1

Yet another way to cut it:

Application.cfc

<cfcomponent displayname="Application" output="false" hint="Handle the application.">

<!--- Set up the application. --->
<cfset this.Name = "AppCFC" />
<cfset this.ApplicationTimeout = createTimeSpan( 1, 0, 0, 0 ) />
<cfset this.sessionTimeout = createTimeSpan( 0, 0, 30, 0 ) />
<cfset this.sessionManagement = true />

<cffunction
    name="OnApplicationStart"
    access="public"
    returntype="boolean"
    output="false"
    hint="Fires when the application is first created.">
    
    <!--- These variables are available to every CFM page in the application --->
    <cfset application.lib = new path_to_Lib_CFC()>

    <cfset application.footer=application.lib.getFooter()>
    
    <cfreturn true />
</cffunction>

</cfcomponent>

Lib.cfc

<cfcomponent displayname="Lib" hint="Library of application CFCs">

<cffunction 
    name="getFooter" 
    output="false" 
    access="public" 
    returnType="string">
    
    <cfset var footer = "<footer class=""text-center"">I am a footer.</footer>" />

    <cfreturn footer />
</cffunction>

</cfcomponent>

Then, in any CFM file in the application:

<cfoutput>#application.footer#</cfoutput>
BKBK
  • 484
  • 2
  • 9
0

I am going to ask and answer what I think you want.

Question

I have an application and it needs to have common footers. My footers are going to need the ability to have some sort of business logic. Right now it is Just static text. I think my footers need to be a function.

How can I do that? Oh, and I need to do this with tags, not script

Answer

First, we need a function with a very wide scope. I am going to put it in application.cfc. It is true that application.cfc is a .cfc, but it is highly special.

<!--- application.cfc --->
<cfcomponent>
...
<cffunction name="getFooter">
    <cfsavecontent variable="local.result">

    </cfsavecontent>

    <cfreturn local.result>
</cffunction>

<cfset application.getFooter = getFooter>
...
</cfcomponent>

Now inside of each of the .cfm files, you can

<cfoutput>#application.getFooter()#</cfoutput>
James A Mohler
  • 11,060
  • 15
  • 46
  • 72
  • Are you sure you have all the necessary parentheses? – Dan Bracuk Jul 24 '20 at 12:23
  • The line `` is incorrectly placed. It should be in onApplicationStart rather than in the pseudoconstructor. Nevertheless, your idea - of using the fact that a function is just another variable - is neat. – BKBK Jul 24 '20 at 13:39
0

Turns out this was a lot simpler than most us made it out to be. The <cfsavecontent> tag wasn't necessary. Storing the HTML in a variable wasn't required. I don't know if it was me or not, but this got way over complicated.

Ultimately, this is where I ended up going.

lib.cfc file

<cffunction name="getFooter" output="true" access="public" returntype="string">
    <footer>I am a footer.</footer>
</cffunction>

index.cfm file

<cfoutput>
    #application.lib.getFooter()#
</cfoutput>
Millhorn
  • 2,953
  • 7
  • 39
  • 77
  • It's good that you solved your problem. However, since this question is now a reference for others who might face similar issues, I'm going to challenge the statement, `Nor was creating a new object`. An object is in fact required in order to access a component's functions. You didn't need a new one because you already had one. If you check your application.cfc file, you will most likely find the code to create the application variable, `application.lib`. – Dan Bracuk Jul 25 '20 at 12:45
  • You are right @DanBracuk, and I have edited my answer above. In my application.cfc, I have ``. – Millhorn Jul 25 '20 at 18:59
0

I find it useful to just put simple reuseable things in their own CFM and just include them when needed.

/app/includes/footer.cfm

<p>I am the footer</p>

index.html

<cfinclude template="app/includes/footer.cfm">
  • But includes can become overbearing and do harm to the page's logic. – Millhorn Jul 27 '20 at 16:13
  • Horse hockey - no harm if used correctly - From the documentation: RECOMMENDED USES Consider using the cfinclude tag in the following cases: For page headers and footers To divide a large page into multiple logical chunks that are easier to understand and manage For large "snippets" of code that are used in many places but do not require parameters or fit into the model of a function or tag – Eric Searing Jul 27 '20 at 21:02