The problem below is a puzzle, which I have not solved, but found a way to deal with. I finally tore apart xref2.cfm and put it back together one line at a time. As soon as I did that, the form scope began to work. Nothing changed in the code. So it remains a mystery.
I have a set of 4 procedures which are linked together like this:
person1.cfm: this originates with a call from another program and a url argument basetab=Person . I'm focusing here on the variable "fn".
<cfif IsDefined('URL.basetab')>
<cfset basetab = URL.basetab>
<cfset perloc = URL.perloc>
<cfset fn = ''>
<cfset ln = ''>
<cfset eof = "no">
however person1.cfm may also be accessed with a cfinclude further down the line, in which case I rely on the form scope to pass fn back to person1.cfm
<cfelseif IsDefined('form.fn')>
<cfset fn = form.fn>
<cfset ln = form.ln>
<cfset basetab = form.basetab>
<cfset perloc = form.perloc>
<cfset eof = form.eof>
</cfif>
however, if neither the URL scope nor the form scope is defined here, the variable fn should have been set in a program which is including person1.cfm, so it should be well defined at this point.
... stuff ...
<form action = "person2.cfm" method = "post" ... other stuff>
<input type = "text" name = "fn" value = "#fn#">
.... more stuff....
... submit ...
</form>
person2.cfm: this is the next step in the process
... stuff ...
<cfset fn = form.fn>
<cfinclude template = "person1.cfm">
<form action = "xref1.cfm" method = "post" ... stuff >
<cfoutput>
<input type = "hidden" name = "fn" value = "#fn#">
</cfoutput>
.... stuff ....
.....submit ....
</form>
xref1.cfm this is the next step
... stuff ...
<cfset fn = form.fn>
<cfinclude template = "person2.cfm">
<form action = "xref2.cfm" method = "post" ... stuff >
<cfoutput>
<input type = "hidden" name = "fn" value = "#fn#">
</cfoutput>
.... stuff ....
.....submit ....
</form>
xref2.cfm the final step, where something is done with the accumulated entries
.... stuff ...
<cfset fn = form.fn>
<cfinclude template = "xref1.cfm">
... no form ... other stuff ...
The problem is that in xref2.cfm the variable fn is not being picked up in the form scope. Checking things out, I find that form.fn is not defined at all in xref2.cfm. When things cascade back to Person1, fn is not defined and throws an error in the input tag.
form.fn is defined in person2.cfm and in xref1.cfm. But when we get to xref2.cfm, it disappears. I do not understand why. Can someone explain to me why that form scope is not there in xref2.cfm?
I think it was a typo or something.
Related
I have a form that outputs different items in order the value of the items is coming out properly from the form (Value1,Value2,Value3) however when I try to do the same sort of counting method in my cfsets it does not work.
<cfloop index="u" from="1" to="#arraylen( session.cart )#">
<cfset updateRow = session.cart[u]/>
<cfset session.cart[#u#].Ohm = "#Form.ohmicValue1#">
Essentially what I need the "1" to be is a variable (#u#) but how do I got about landing that within the #Form.OhmicValue[#u#]# I guess is the final question.
Thanks for the help.
Tom
The following should work
<cfloop index="u" from="1" to="#arraylen( session.cart )#">
<cfset updateRow = session.cart[u]/>
<cfset session.cart[u].Ohm = form['ohmicValue' & u]>
</cfloop>
I'm trying to make an xml-rpc call from a coldfusion server. I found this xml-rpc cfc (Thanks, Brad Wood!) that formats the xml for the cfhttp call but I'm struggling with interpretting how to pass in any parameters besides the call name.
Here's the api documention using perl
This is my coldfusion code
<cfobject component="xmlrpc" name="c">
<cfset arr = arraynew(1)>
<cfset arrayappend(arr,"service.show")>
<cfset arrayappend(arr,myVIP)>
<cfset arrayappend(arr,myIP)>
<cfset arrayappend(arr,myPort)>
<cfset myxml = c.CFML2XMLRPC(arr,"call")>
<cfhttp url="#apiUrl#" method="POST">
<cfhttpparam name="request_body" value="#myxml#" type="XML">
</cfhttp>
The error message that I keep getting is:
Can't use string (myVIP...) as a HASH ref while "strict refs" in
use at /home/...
So what I don't understand is how to translate the notation I see in perl of {parameter1=>'value1',parameter2=>'value2'} to the array that I'm passing into CFML2XMLRPC.
I figured it out and now it seems so obvious... You have to use a struct to hold the parameters and pass that into the array after the method string.
<cfset arr = arraynew(1)>
<cfset arrayappend(arr,"service.show")>
<cfset paramObj = structnew()>
<cfset paramObj['vip'] = myVIP>
<cfset paramObj['ip'] = myIP>
<cfset paramObj['port'] = myPort>
<cfset paramObj['show'] = "status/state">
<cfset arrayappend(arr,paramObj)>
I found the jquery xml-rpc documentation helpful to understanding how the xml should actually be formatted.
Note: the notation of
<cfset paramObj['ip'] = myIP>
vs
<cfset paramObj.ip = myIP>
is important since the latter will result in all uppercase for the parameter name in xmlrpc.cfc. (thanks to comment by Dave Merrill on this post)
We need to create html dropdown list dynamically. Following is our current code. Option1 and Option2 are strings that include all the items. The reason we have two strings is we split all the items in two groups.
<td>
<div id="dvGroup" style="display:none;" runat="server"></div>
</td>
string Option1 = "<optgroup label='Group1'><option>1</option><option1>2</option>";
string Option2 = "<optgroup label='Group2'><option>a</option><option>b</option><option>c</option>;
…
dvGroup.InnerHtml = "<Select name='ddGroup' id='ddGroup'>" + Option1 + Option2 + "</Select>";
But by setting InnerHtml will potentially bring some security problem. So I changed it to:
HtmlSelect select = new HtmlSelect();
select.ID = "ddGroup";
select.Name = "ddGroup";
select.ClientIDMode = ClientIDMode.Static;
dvGroup.Controls.Add(select);
select.Controls.Add(new LiteralControl(Option1 + Option2));
However, it threw following error at the line select.Controls.Add…
'System.Web.UI.HtmlControls.HtmlSelect' does not allow child controls.
How do I fix this? Another problem is, setting ClientIDMode to Static only make sure the id is not changed, but name still being added extra stuff. How do I make sure name is not changed either?
You can do this way:
HtmlSelect mHtmlSelect = new HtmlSelect();
mHtmlSelect.ID = "ddGroup";
mHtmlSelect.Name = "ddGroup";
mHtmlSelect.ClientIDMode = ClientIDMode.Static;
String Option1 = "Hello";
String Option2 = "World";
mHtmlSelect.Items.Add(new ListItem(Option1 + Option2));
this.Controls.Add(mHtmlSelect);
Output:
<select name="ddGroup" id="ddGroup">
<option value="HelloWorld">HelloWorld</option>
</select>
I'm looking for a way to declare form default values dynamically in a CFC, I'm calling via AJAX. The current CFC sends orders, which I need to break down into sub-orders.
I had been using this:
<!--- static defaults --->
<cffunction name="Defaults" access="public" returntype="struct" output="false"
hint="Assign default values to instance">
<cfscript>
var formDefaults = {
versenden=""
, speichern=""
...
}
</cfscript>
<cfreturn formDefaults />
</cffunction>
<cffunction name="Commit" access="public" returntype="struct" output="false" hint="database handler">
<!--- add dynamic form fields --->
<cfscript>
var LOCAL = {};
variables.defs = THIS.Defaults();
</cfscript>
<cfloop collection="#VARIABLES.Instance.FormData#" item="formField">
<cfscript>
if ( LEFT(formField, 5) EQ "MENGE"
OR LEFT(formField, 3) EQ "EAN"
OR LEFT(formField, 12) EQ "BESTELL_TEXT"
OR LEFT(formField, 10) EQ "BESTELLTYP"
...
) {
variables.defs[formField]="";
}
</cfscript>
</cfloop>
<cfscript>
structAppend(variables.defs, VARIABLES.Instance.FormData);
LOCAL.Basket = variables.defs;
</cfscript>
...
So I first declare static form fields (single instance only) and then try to dynamically append dynamic form fields to my array, which might be transferred multiple times (MENGE38, MENGE39, MENGE40 etc)
While this works ok, I need to add another counting element to my form-names, so I would have to change MENGE to something like counter.MENGE or MENGE.counter which will then send form values like this:
MENGE.1.38
MENGE.1.40
MENGE.1.41
MENGE.2.37
With the counter denoting the sub-order, this field is used for.
Problem is, this breaks my dynamic form field declaration and I don't understand why. I'm getting the following errors:
Diagnose: Element MENGE.1 is undefined in a CFML structure referenced as part of an expression.
Question:
Can anyone give me a hint on what the problem might be? Do I have to param the form fields on the HTML page as well (shouldn't have to)?
Thanks!
EDIT:
Problem was in my validate function, I also need to declare the modifications I did above. The new function looks like this:
<cffunction name="Validate" access="public" returntype="array" output="false" hint="validate form inputs and return an array of faulty field names.">
<cfscript>
var LOCAL = {};
var double = structNew();
double.form = VARIABLES.Instance.FormData;
double.criteria = VARIABLES.Instance.Validation;
</cfscript>
<!--- add dynamic form fields for validation... I FORGOT TO UPDATE THIS--->
<cfloop collection="#VARIABLES.Instance.FormData#" item="formField">
<cfscript>
if ( LEFT(formField, 5) EQ "MENGE"
OR LEFT(formField, 10) EQ 'BESTELLTYP'
OR LEFT(formField, 3) EQ "EAN"
OR LEFT(formField, 12) EQ "BESTELL_TEXT"
...
) {
VARIABLES.Instance.Validation[formField]="pass";
}
</cfscript>
</cfloop>
<!--- Get error names and type --->
<cfinvoke component="form_validate" method="validate_fields" double="#double#" returnvariable="validation_errors"></cfinvoke>
<cfset LOCAL.ErrorMessages = validation_errors />
<cfreturn LOCAL.ErrorMessages />
Because I did not add the new updated the if-clause in this function, I was getting the error.
To build on Dan Bracuk's answer, use underscores (though you'd need to change the name of "BESTELL_TEXT"). Use this with a combination of listFirst, listGetAt, and listLast to determine field name structure, using underscore as delimiter. Note how I cleaned up your big IF a bit using list function. This code as written probably doesn't do what you need, but wanted to illustrate the concepts without having to understand your business need.
<cfscript>
var orders=structNew();
item=listFirst(formField,'_');
orderNames = "MENGE,EAN,BESTELLTEXT,BESTELLTYPE";
if (listFindNoCase(orderNames,item,'_')){
if (!structKeyExists(orders,item)){
// initialize item
orders[item]=structNew();
}
orderID="";
subOrderId="";
if (listLen(formField,'_') gt 1) {
orderID=listGetAt(formField,2,'_');
}
if (listLen(formField,'_') eq 2) {
orders[item][orderId]=formData[formField];
}
if (listLen(formField,'_') eq 3) {
subOrderId=listLast(formField,'_');
orders[item][orderId][subOrderId]=formData[formField];
}
}
</cfscript>
In trying to work around the buggy <cfhttp> SSL implementation, I switched to using COM and MSXML2.ServerHTTP directly. Unfortunately the POST data fails to arrive at the destination page. GET works, but I'd rather not use it, since I have no idea if the request urls are logged and I don't want to pass sensitive data if I can help it. (Am I worrying too much?)
My problem is similar to this one: http://objectmix.com/xml-soap/87408-sending-post-variables-using-msxml2-serverxmlhttp-3-0-a.html
Here's my code:
<cfset querystring = "?CustomerID=#CustomerID#&OrderDelRecipient=#OrderDelRecipient#&OrderCompany=#OrderCompany#&OrderTelephone=#OrderTelephone#&OrderNotes=#OrderNotes#&OrderDelStreet=#OrderDelStreet#&OrderDelCity=#OrderDelCity#&OrderDelState=#OrderDelState#&OrderDelZip=#OrderDelZip#">
<cfobject type="COM" action="Create" name="objSrvHTTP" class="MSXML2.ServerXMLHTTP.3.0">
<cfset urlstring = "http://www.pascaltechnologies.com/saveorder.cfm">
<cfset temp = objSrvHTTP.open("post", urlstring, false)>
<cfset temp = objSrvHTTP.setRequestHeader("Content-Type", "application/x-www-form-
urlencoded")>
<cfset temp = objSrvHTTP.send("#querystring#")>
<cfset FileContent = objSrvHTTP.responsetext>
<cfoutput>
#filecontent#
</cfoutput>
When I check for the Form vars on the called page (saveorder.cfm)
<cfif Not IsDefined("CustomerID") OR NOT IsNumeric(CustomerID)>
ERR 609 - INVALID PARAMETERS PASSED.
<cfabort>
</cfif>
they are empty, so the above code gets triggered.
Is this because I need to copy the response to the form var? e.g. <cfset FORM.CustomerID = objSrvHTTP.CustomerID> (You'd think it wouldn't be necessary since it isn't needed with GET.) Or am I simply not implementing something correctly?