Skip to main content
Known Participant
January 3, 2007
Question

Dynamically creating a CF Tag

  • January 3, 2007
  • 9 replies
  • 1927 views
Greetings,

I would like to dynamically determine what attributes are present in a ColdFusion tag. I have done the following to test the theory:

<cfset inputAttr['name'] = "tControlName">
<cfset inputAttr.label = "Control Label">
<cfset inputAttr.value = "Some string value">
<cfset inputAttr.type = "text">

<cfform name="fTest" method="post" action="">
<cfset tagAttr = "<cfinput ">
<cfloop collection=#inputAttr# item="attr">
<cfset tagAttr = '#tagAttr# #attr#="#inputAttr[attr]#"'>
</cfloop>
<cfset tagAttr = "#tagAttr# >">
<cfoutput>#tagAttr#</cfoutput>
</cfform>

If I look at the source for the page it is correct, but no input is creates. If however I change it to "<input" instead of <cfinput" it works fine. Unfortunately I would like to use attributes like validate that are only available in <cfinput>.

I assume that the stuff within the <cfoutput> tags are bding sent directly to the browser and bypassing the processing be CF. So I have tried leaving out the "<cfinput " and ">" from the tagAttr and using the following:

<cfinput "#tagAttr#" >

in a variety of forms but keep getting an error of one sort or another.

Am I missing something or is this not possible?

Thanks for your help.
This topic has been closed for replies.

9 replies

January 5, 2007
um.. that tag will cfmlevaluate (as i like to call it ;p) whatever you put in there. Why not create a big long string with loads of cfinputs in it and cfmlevaluate that?

p.s.
there is no reason to suck up to that Aussie wierdo cameron ;)
Known Participant
January 5, 2007
Thank you for pointing that out. I had a more careful look and see what is happening. I have been under the weather and see the Dr. soon to see what is going on. It is like my head is full of molasses.

As for Adam, he is a Kiwi and I think he has stopped using the spade. And he does seem to know how cf works, so if I learn something from him it is good. And I can learn from you as well.
Known Participant
January 5, 2007
Hi,

I had a look at the source generated and found that both the <cfinput...> and the <input...> tags were present. Of course the <cfinput...> did not display at all.

I had a look at the file content and only the <cfinput...> text was present. I determined that the cfoutput displayed the data and passed it to the tag which wrote the file and then included it. So I made a slight change and passed the tag as an attribute and everything came out fine.

Now I will look at it and see if how easy it will be to create forms in this manner.

Thanks for your help.
January 5, 2007
<cfform name="fTest" method="post" action="">
<cfset field = '<cfinput name="wiggy" id="wanky" required="true" />'>
<cf_saveandinclude>
<cfoutput>#field#</cfoutput>
</cf_saveandinclude>
</cfform>

saveandinclude.cfm

<cfif thisTag.executionMode IS "end">
<cfset filename = "#createuuid()#.cfm">
<cfset filepath = expandPath(filename)>
<cffile action="write" file="#filepath#" output="#thisTag.GeneratedContent#">
<cfinclude template="#filename#">
<cffile action="delete" file="#filepath#">
</cfif>
Known Participant
January 5, 2007
Thanks Monkey Woo Too,

That is a nice simple solution. Is the file access going to greatly affect the performance? I would call this for each field on the form. There could be 10 or more fields. I could modify the code perhaps to have a tag open the file, a second tab to write to the file, and a third to close, include and delete the file. That might be more efficient.

Inspiring
January 3, 2007
> If you can show
> me some Java, JavaScript, VB or any syntax that creates a line of code
> and then runs that line of code, it can probably be done in CF.

You actually CAN do it in JS:

<html>
<head>
<title>Change Me</title>
<script type="text/javascript">
function runTimeJs(){
var s = '<script type=\"text/javascript\">a'+'lert(\"Boo!\");
d'+'ocument.title=\"New Value\";' + '<'+ '/script>';
alert('writing: '+s);
document.write(s);
}
</script>
</head>
<body onload="runTimeJs()">

</body>
</html>


Note that the function body is just writing a string, the string being:
<script type="text/javascript">alert("Boo!"); document.title="New
Value";</script>

I've broken up the JS instructions in the string to demonstrate it's NOT
simply executing the code as it hits it... it's executing the STRING of
code, once it's written to the document.

--
Adam
Inspiring
January 3, 2007
> <cfset x = 'value="Dan is smart"'>
> <cfform>
> <cfinput #x#>
> </cfform>

Unfortunately Dan is not as smart as he'd have us believe (you left
yourself open for that one, mate).

This won't work for the reason Ian stated: you cannot USE CF code to create
more CF code within the same file.

It's nonsensical, if you stop to think about it. CF does not read the file
in line by line, so you cannot have CFML on line 10 of a file which creates
more code on line 15 which you somehow expect to execute simply because you
output it. Remember: CFML files get COMPILED before they're executed for
one thing. So how can you create code at run-time which needed to already
be there at compile-time to get compiled so it can then be run? Short of
having some sort of CFML Tardis, that is.

Even if that would work, how would you expect just OUTPUTTING something
that looks like code to actually be compiled and then run?

So, yeah: nonsensical.

If you MUST do this, then you have to do what he said: write the CFML to a
FILE, and then <cfinclude> the file.

--
Adam
Known Participant
January 3, 2007
Thank you Adam for your comments. I understand what you are saying. But , I believe the following line of code is valid:

<cfinput name="#name#" value="#someValue#">

So how different is it to want to specify the what attributes you might like on the fly?

In the end, it may not be possible. In which case I will take a different approach. But perhaps there is someone out there that can see something I am missing.
Inspiring
January 3, 2007
There is a reason for doing it. It may not be as important in CF as
other technologies. The intent is to minimize the number of times I
have to enter certain infomation. For example, I can declare the form
control name, the label, the database column, and other information in
one place. Then when I create the form, I can have a function that
takes the information and creates the control. When the form is
submitted, it uses the same control name and knows the database column
so can store the data in the db, or retrieve it from the db. This has
saved me a huge amount of time using other technologies.

This can be done in CF as well. Custom tags and Components come to
mind. But <cfinput ...> in essance already is a control. It creates
blocks of JS and HTML in the output returned to the client.

You are trying to create on the fly CFML and run it at the same time.
Honestly I don't know how to do this in ANY language. If you can show
me some Java, JavaScript, VB or any syntax that creates a line of code
and then runs that line of code, it can probably be done in CF.
Inspiring
January 3, 2007
Put it in quotes.
Known Participant
January 3, 2007
Thanks you once again Dan.

That was the second thing I tried. It gave the following error:

Invalid token '"' found on line 57 at column 18.

That was when I started making more complicated statements.

Thanks again for the suggestion.
Inspiring
January 3, 2007
Try this:

<cfset x = 'value="Dan is smart"'>
<cfform>
<cfinput #x#>
</cfform>

If that works, apply the same concept to what you are really trying to to.
Known Participant
January 3, 2007
Thanks for the suggestion Dan.

It was one of the first things I tried. It gives the following error:

<b>Invalid CFML construct found on line 57 at column 18.
ColdFusion was looking at the following text:

#

The CFML compiler was processing:

* a cfinput tag beginning on line 57, column 10.

</b>

Thanks agian for your help.
Known Participant
January 3, 2007
Thanks for your input.

It does seem to be unnatural in CF, and I will probably abandon this approach.

There is a reason for doing it. It may not be as important in CF as other technologies. The intent is to minimize the number of times I have to enter certain infomation. For example, I can declare the form control name, the label, the database column, and other information in one place. Then when I create the form, I can have a function that takes the information and creates the control. When the form is submitted, it uses the same control name and knows the database column so can store the data in the db, or retrieve it from the db. This has saved me a huge amount of time using other technologies.

For example there might be 10 statement required to test that a sql query was successful. That all goes in one function, which can be done in CF. But I still have to remember the control name and the column name, and type them correctly every time I use them, and make the proper conversions. In the past 5 years my memory has deteriorated and I make more errors. And some times it isn't easy to figure out where the error is - script,. JavaScript, sql, or html?

It is true that CF makes it easier to do some of the tasks that I did using objects in other technologies, so I may not save as much time. For example CF generates JS validation code. One less thing for me to worry about. But it is still boring to write another sql insert or update statement.

I am looking at other alternatives to accomplish the goal in CF.

Thanks again for your help.

Inspiring
January 3, 2007
Am I missing something or is this not possible?

Thanks for your help.

What you are attempting to do is very unnatural. Why it works with
<input...> is that is HTML, and what CFML does is create HTML, or
JavaScript, or CSS, or other CLIENT side technologies.

You are attempting to create CMFL. This is not a very native thing to
do. One way I have seen it successfully attempted is to create the
entire <cfinput ...> tag as a string, write that string to a file and
then <cfinclude...> that file later on for processing.

But one really has to question the requirements when something like this
is attempted. What is the purpose? Maybe there is a better way to
accomplish the requirement that is not so klugy sounding.