views:

340

answers:

4
+3  Q: 

cffunction Access=

If I use access="remote" for binding a cfselect to a cfc, then I lose the ability to have an Init() constructor.

<cfselect name="CityID" bind="cfc:Components.City.View1({StateID})" value="CityID" display="CityName" bindonload="yes" />

I'm used to passing the datasource name to the Init function when I instantiate a component, like so:

<cfcomponent>
<cffunction name="Init">
<cfargument name="DS">

<cfset Variables.Instance.DS = arguments.DS>
<cfreturn This>
</cffunction>

<cffunction name="View1">
<cfset var qry = "">

<cfquery name="qry" datasource="#Variables.Instance.DS.Datasource#">
SELECT *
FROM Table
</cfquery>
<cfreturn qry>
</cffunction>
</cfcomponent>
+1  A: 

What is the question, exactly?

Setting a CFC to remote is basically making it a web service, so I guess that is why you wouldn't have the init() constructor.

You could easily set the datasource name in an application/session variable that created in the onApplicationStart portion of your application.cfc file.

Jason
A: 

Is there a reason why you might not want to create your own remote init function that calls the one you can't reach for you?

Maybe a pain to do it that way.. just food for thought.

Jas Panesar
+4  A: 

Phillip, what I usually do in this scenario is:

  1. Create the object in onApplicationStart, and store it to the Application scope. This is where you will initialize with your datasource other settings.
  2. Create a remote-proxy CFC that is basically a stub for the real thing, and bind your select field to that CFC.

onApplicationStart:

<cffunction name="onApplicationStart">
  <cfset application.dsn = "myDSN" />
  <cfset application.cityFinder = createObject("component", "Components.City").init(application.dsn) />
</cffunction>

And the remote proxy CFC:

<cfcomponent displayName="CityFinderProxy">
  <cffunction name="View1">
    <cfargument name="StateId" />
    <cfreturn application.cityFinder.View1(argumentCollection=arguments) />
  </cffunction>
</cfcomponent>

Note that I've left out a lot of best-practices (i.e. specifying argument types, required, etc) for brevity... so don't just copy and paste this example. I just wanted to illustrate the idea.

Adam Tuttle
Adam, what a great reply! That's is very helpful. The only problem I have now is that you are using the Application scope inside a cfc.
cf_PhillipSenn
Remote proxy objects are a special case. I've yet to come across a better implementation than this. You could use ColdSpring to create these remote proxies, but they will work the same way. http://coldspringframework.org/coldspring/examples/quickstart/index.cfm?page=remote
Adam Tuttle
+1  A: 

What we have done: enacted a software development standard that outlaws any constructor code in our in-house developed components except a single (optional) invocation of the init() method. The so-called constructor code (anything inside the cfcomponent tag that is not inside a cffunction tag) will still get run in when the object is instantiated, and as a result before your method is actually called.

<cfcomponent>

  <cfset init() />

  <cffunction name="init">
    <cfset variables.message = "Hello, World" />
    <cfreturn this />
  </cffunction>

  <cffunction name="remoteMethod" access="remote">
    <cfreturn variables.message />
  </cffunction>

</cfcomponent>
Goyuix
This is a good idea, but it doesn't handle passing variables into the constructor. I've gotten used to passing the datasource into the init to populate variables.instance.datasource.
cf_PhillipSenn
You can certainly add optional parameters to your init method - in fact, we prefer to have one optional argument that is a struct we need to pass in parameters, and you can pass in whatever other data you need through that. The only downside is that init will be called twice.
Goyuix