MWT
MWT

Reputation: 53

How to refer to variables when the names are indefinite and must be found by regex first, using Coldfusion?

I have an html form that collects variables that look like:

ent1_label
ent2_label

ent1att1_label
ent1att2_label
ent2att1_label
ent2att2_label

ent1att1val1_label
ent1att1val2_label
...
ent2att2val2_label

I don't know in advance how many of ent, att, or val will be coming from the form to the action script. In the input form, I run loops that concatenate the variable names:

ent<cfoutput>#i#</cfoutput>att<cfoutput>#j#</cfoutput>val<cfoutput>#k#</cfoutput>_label
(where i, j, and k are the number of ent, att, and val)

This works great on the input form, but then I'm lost on how to refer to them in the action script.

I've played around with #form.fieldnames# which has all of the actual variable names.

<cfset #formfields# = listToArray(#form.fieldnames#, ",")>
<cfset #formlength# = arraylen(#formfields#)> 
<cfset #entattval_label# = arrayNew(1)>
<cfloop from="1" to="#formlength#" index="i">
<cfif REfind("ENT[0-9]*ATT[0-9]*VAL[0-9]*_LABEL", #formfields[i]#) EQ 1>
<cfset arrayAppend(entattval_label, "#formfields[i]#")>
</cfif>
</cfloop>

will make separate arrays for each subset of variables I need. But how do I make it print the contents of the variables, instead of their names?

<cfset #label_length# = arraylen(#entattval_label#)>
<cfloop from="1" to="#label_length#" index="i">
<cfoutput>#entattval_label[i]#</cfoutput>
</cfloop>

Upvotes: 0

Views: 79

Answers (2)

Regular Jo
Regular Jo

Reputation: 5510

(Too long and too much formatting for an easily-readable comment.)

Just for the record, you can significantly shorten your code by using ReMatchNoCase() instead of ReFind() if you're using CF8+ or Railo.

ReMatchNoCase (and ReMatch of course) looks for as many matches as possible. I created a form.fieldnames variable for demonstration but that's not even really needed

<cfset form.fieldnames = "ent1_label,ent2_label,notvalid,btnSelect,ent1att1_label,ent1att2_label,ent2att1_label,ent2att2_label,ent1att1val1_label,ent1att1val2_label,ent2att2val2_label">
<Cfset NamesArray = REMatchNoCase("ENT[0-9]*ATT[0-9]*VAL[0-9]*_LABEL",form.fieldnames)>
<cfoutput><cfloop from="1" to="#ArrayLen(NamesArray)#" index="i">
    #NamesArray[i]#: #form[NamesArray[i]]#<br />
  </cfloop>
</cfoutput>

Upvotes: 1

Adam Tuttle
Adam Tuttle

Reputation: 19804

You can reference a variable with a dynamic name using what's called array notation:

foo.bar can also be written as foo['bar'] - even though it's a structure and not an array.

This means that you can inject any dynamic name into your reference that you like; and this also works for built in variable scopes like form, url, etc:

For example: form['ent#i#att#j#val#k#_label'] where i, j, and k are the integers you need.

If you find that hard to read, you could also write it as:

form['ent' & i & 'att' & j & 'val' & k & '_label']

In these situations, if the form is being expanded on the client-side (e.g. with JavaScript) without server involvement, I often find it's easiest to include a numeric hidden field (or in your case, maybe 3?) to indicate the ranges for i, j, and k.

Upvotes: 10

Related Questions