I have 2 files: test.cfc and test.cfm. When I click the submit button in test.cfm, I am getting the following error:
"error: Object doesn't support this property of method".
I know it has something to do with the form reference inside the passForm function. But after googling for hours I am still unable to resolve the error. Any advice?
test.cfc
<cfcomponent>
<cffunction name="getForm" returntype="String" access="remote">
<cfargument name="theForm" type="struct">
</cffunction>
</cfcomponent>
test.cfm
<cfajaxproxy cfc="ajaxFunc.test" jsclassname="testCFC">
<script>
function passForm(theForm)
{
try
{
var e = new testCFC();
message = e.getForm(theForm);
ColdFusion.navigate('', 'myDiv');
}
}
</script>
Have you looked at the serializeJSON() and deserializeJSON() functions in ColdFusion?
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_s_03.html
Also, have a look at the following thread, which may be of help to you.
How to pass STRUCT - OR - JSON to Coldfusion CFC Method
Hope that helps.
Mikey.
Related
I am submitting a form to a CFC which in turn invokes a method in a different CFC. The initial CFC will then send an e-mail to the user confirming its all done. Its a bit like this:
<cfcomponent>
<cffunction name="FinalDemand" access="remote">
<cfinvoke component="AnotherCFC" method="AddToAudit" argumentCollection="#Arguments#">
<!--- I need to wait for confirmation from AnotherCFC here before continuing --->
<cfset APPLICATION.SendMail.ThankYou()/>
<cfset var Success = true>
<cfreturn Success>
</cffunction>
</cfcomponent>
The AnotherCFC is doing an update to a database. I'd really like that method to be able to tell the calling CFC that its done its work. At the moment it just returns a boolean like the CFC above to say all went well. If it doesn't return the boolean then we know it went wrong.
Is this possible at all? I don't mind using JQuery to acomplish it if need be.
I have tried, off and on, for about 6 months or so to figure out CFC's but never could get it. So now I have SQL and LDAP queries scattered around in different pages that I would like to consolidate into a component. The query below works in it's own CF page, (I've omitted some of the query details for the post) but I'm getting a blank page instead of any results. This is my queries.cfc:
<cfcomponent>
<cffunction name="EmployeeQuery" access="public" returntype="query">
<cfargument name="EmployeeID" required="yes" type="string">
<cfldap action = "query"
name = "EmployeeAdd"
attributes = "distinguishedName, displayName"
filter = "sAMAccountName=#Arguments.EmployeeID#"
start = ""
scope="SUBTREE"
maxrows="1"
server = ""
username=""
password=""
separator=";" />
<cfreturn EmployeeAdd>
</cffunction>
</cfcomponent>
I've got a simple entry form where I enter text, click submit, and on the action page I have:
<cfif IsDefined("form.btnEmployeeAdd")>
<cfinvoke component="queries"
method="EmployeeQuery"
cfinvokeargument
name="EmployeeID"
value="#form.txtEmployeeID#">
<h3>Confirm Employee Entered</h3>
<cfoutput>#EmployeeAdd.displayName#</cfoutput>
</cfif>
My result is a blank page, I don't even get the h3 text. As mentioned, all this works fine in .cfm pages, but it craps the bed when I try to put it in a .cfc. As with all documentation on this, there's so many different ways to do this, but nothing I've tried works so I was hoping I could get a push in the right direction.
Your cfinvoke is missing a returnVariable
<cfinvoke component="queries" method="EmployeeQuery" returnVariable="EmployeeAdd">
<cfinvokeargument name="EmployeeID" value="#form.txtEmployeeID#">
</cfinvoke>
<h3>Confirm Employee Entered</h3>
<cfoutput>#EmployeeAdd.displayName#</cfoutput>
Alternatively if you're on CF10 or higher you could do this instead of your cfinvoke
<cfset employeeAdd = new queries().EmployeeQuery(form.txtEmployeeID)>
Looking at your code to invoke the cfc method, it seems like you are doing it in a wrong way. You have added cfinvokeargument inside cfinvoke as an attribute. cfinvokeargument should be added to cfinvoke body, instead. And as #matt suggested you need to add returnvariable attribute to cfinvoke in order to get results returned from the method. Like this.
<cfinvoke component="queries" method="EmployeeQuery" returnVariable="EmployeeAdd">
<cfinvokeargument name="EmployeeID" value="#form.txtEmployeeID#">
</cfinvoke>
Also as #matt suggested, if you are using cf10 or higher you can use new to instantiate the cfc and then call the method using . notation. Like this.
<cfset employeeAdd = new queries().EmployeeQuery(form.txtEmployeeID)>
I've never seen this before I have a component in a cfc file and I use
<cfset request = CreateObject("component","path/to/component") />
When I set request to the above or:
<cfset request = CreateObject("component","path/to/component").init() /> or
<cfset request = CreateObject("component","path/to/component").from_request() />
etc I always get a struct with a single item that is the equivilant of
{cfdumpinited = false}
I've never see this before. The from_request method reuturns init and init returns this.
When I <cfdump this> right before the <cfreturn this> I get the full object output on the screen. But when I <cfdump request> I get the struct stated above. Anyone know what causes Coldfusion to return this type of struct. I can post the entire cfc but I don't think that will help as I stated, right before the return I can output this and it is the entire object/component.
request is a scope in ColdFusion, therefore you should use another variable name.
I am learning Framework1 and tried to do a simple ColdFusion program to insert data into database after submitting a form.
My simple form person.cfm is in views/main
<form name = "savePerson" action="#buildurl('person')#" method="post">
In the form action I put controller person.cfc
I have person.cfc in controllers folder with code in the component
<cffunction name="person">
<cfif isDefined("rc.savePerson")>
<cfset variables.services.person.savePerson()>
</cfif>
</cffunction
and SQL insert statement in person.cfc with function name = savePerson in the services folder.
Application.cfc has code
function setupApplication() {
var bf = new framework.ioc( "services" );
setBeanFactory( bf );
}
When I submit the form I get the error below
Original exception in onRequest
The action person.person failed.
Element SERVICES.PERSON is undefined in a Java object of type class [Ljava.lang.String; referenced as ''
(Expression)
but there is a person.cfc in controllers, services. I don't know if I need a beans folder.
My question is what should I write for form action and how Framework1 will call the file in services folder to run insert statement via controller?
I have a feeling you might be missing get/set to the Person Service. Also make sure you've got the service declared in the beans.xml.cfm
controllers/person.cfc
<cffunction name="setPersonService" access="public" output="false">
<cfargument name="personService" type="any" required="true" />
<cfset variables.personService = arguments.personService />
</cffunction>
<cffunction name="getPersonService" access="public" returntype="any" output="false">
<cfreturn variables.personService />
</cffunction>
assets/config/beans.xml.cfm
<bean id="personService" class="myapp.services.Person" singleton="true">
</bean>
Edit: Oh I just realised this question was answered on the FW/1 groups
I have a ColdFusion CFC function like this:
<cffunction access="remote" name="getResults"
returntype="struct"
returnformat="JSON"
output="no">
<cfargument name="q" required="true" type="array" />
...
</cffunction>
How do I call this function from jQuery? Neither form of array encoding by jQuery will get ColdFusion to see the value as array.
If you pass "q=a&q=b" (like with jQuery.ajaxSettings.traditional = true), the function will get the string "a,b", not an array. While splitting on comma may seem like a possibility, it will not work if one of the "q" values contains a comma. Also, ideally, the function on the server-side should not have to be aware of the problems of how to serialize the data over the wire, and should continue to take in an array.
If you pass "q[]=a&q[]=b" (the jQuery default), it will not map over to the "q" parameter. If you try to change the name of the "q" parameter to "q[]", the CFC will error out due to an invalid parameter name.
First thing to know is jQuery Ajax requests do not encode arrays so have you to use something else to encode the data (this is where jquery.JSON.js comes from referenced below). So with a the JSON encoded found there, I then figured out the correct syntax by working with cfajaxproxy and studying the URL it generates in Firebug:
http://localhost/remote.cfc?method=getResults&argumentCollection=%7B%22q%22%3A%5B1%2C2%5D%7D
Yes the "argumentcollection" approach is correct, and the variable "q" with a reference to an array is in there.
I used the following code as a test bed:
remote.cfc
<cfcomponent output="false">
<cffunction access="remote" name="getResults"
returntype="struct"
returnformat="JSON"
output="no">
<cfargument name="q" required="true" type="array" />
<cfreturn {a=1,b=2}>
</cffunction>
</cfcomponent>
remote.cfm to see how cfajaxproxy generates its url
<cfajaxproxy cfc="Remote" jsclassname="Remote">
<cfoutput>
<script language="javascript" type="text/javascript">
var oRemote = new Remote();
alert(oRemote.getResults([1,2]));
</script>
</cfoutput>
remote.html doing it with jQuery
<script language="javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script language="javascript" src="jquery.JSON.js"></script>
<script language="javascript" type="text/javascript">
var argumentCollection = { q: [1,2] };
$.ajax({
url: 'remote.cfc',
data: {
method: 'getResults',
argumentCollection: $.JSON.encode(argumentCollection)
},
success: function(response) {
alert(response);
},
dataType: 'json'
});
</script>
Investigating this problem, I found the following blog post:
http://www.coldfusionjedi.com/index.cfm/2010/3/23/Using-jQuery-to-post-an-array-to-a-ColdFusion-Component - This suggested encoding the array as a JSON string, and then deserializing it inside the CFC method, with the unfortunate impact of requiring the CFC function to have to change to deal with JSON.
So I investigated further, and here's the best solution I have found so far.
By looking at the HTTP calls made when using cfajaxproxy, I discovered that you can send a single argumentCollection parameter as a JSON string to call the remote CFC method.
So the client side call looks something like this (using jquery-json plugin to do the serialization):
var params = {q: ['a', '1,2,3']};
$.getJSON('My.cfc?method=getResults', {argumentCollection: $.toJSON(params)}, function(data) {
// handle data
});
How about checking your values for commas and escaping them before passing to Coldfusion, then use ListToArray to convert and (if necessary) re-encode the commas?