ftWatch Example

Easy ftWatch Example

Here is a quick primer on how to use ftWatch in a formtool. Basically, two things get passed into the functions of a formtool (such as edit() or display()):

  1. stMetadata
  2. stObject

"stMetadata" is a structure that has all the metadata of the <cfproperty> tag that the call is made for. So, if you've defined ftWatch, it's value is sitting in "arguments.stMetadata.ftWatch". The stObject is all the data of the entire form (as it stands at the moment the function is called). So, say you define a string type to have a ftWatch="bBool", where bBool is the name of another <cfproperty> that you want to trigger on. When the value of that watched property changes, the edit() function of the string property is called. How do you know what the value is of the "bBool" property? Easy: the stObject!

Ok, let's get more specific. This is a sample edit() function for a formtool such as 'string'. (farcry.core.packages.formtools.string). Note that the only difference between this and a function such as display() is the use of super.edit() vs. super.display().

ftWatch Example
<cffunction name="edit" access="public" output="true" returntype="string" hint="his will return a string of formatted HTML text to enable the user to edit the data">
	<cfargument name="typename" required="true" type="string" hint="The name of the type that this field is part of.">
	<cfargument name="stObject" required="true" type="struct" hint="The object of the record that this field is part of.">
	<cfargument name="stMetadata" required="true" type="struct" hint="This is the metadata that is either setup as part of the type.cfc or overridden when calling ft:object by using the stMetadata argument.">
	<cfargument name="fieldname" required="true" type="string" hint="This is the name that will be used for the form field. It includes the prefix that will be used by ft:processform.">

	<cfset var html = "" />
	<cfset var jsscript = "" />

	<cfif structkeyexists(arguments.stMetadata,"ftWatch") and len(arguments.stMetadata.ftWatch)
		AND structkeyexists(arguments.stObject,"#listfirst(arguments.stMetadata.ftWatch)#") 
		AND ( 
				( isValid("boolean",arguments.stObject[listfirst(arguments.stMetadata.ftWatch)]) 
					AND NOT arguments.stObject[listfirst(arguments.stMetadata.ftWatch)] )
				OR NOT len( arguments.stObject[listfirst(arguments.stMetadata.ftWatch)] )
			)	>

		<cfsavecontent variable="jsscript"><cfoutput>
			<script type='text/javascript'>
				var el = Ext.get('#arguments.fieldname#ajaxdiv')
				if (null != el) {
					if (el.parent("div").parent("div").is('div.fieldSection') ) {
						el.parent("div").parent("div").setStyle('display','none');
					}
				}
			</script>
		</cfoutput></cfsavecontent>

		<cfset html = jsscript />
		
	<cfelse>
		<cfsavecontent variable="jsscript"><cfoutput>
			<script type='text/javascript'>
				var el = Ext.get('#arguments.fieldname#ajaxdiv')
				if (null != el) {
					if (el.parent("div").parent("div").is('div.fieldSection') ) {
						el.parent("div").parent("div").setStyle('display','block');
					}
				}
			</script>
		</cfoutput></cfsavecontent>
		<cfset html = jsscript & super.edit(argumentCollection="#arguments#") />
	</cfif>
	
	<cfreturn html>
</cffunction>

The <cfif> structure is simply there to check that all the proper metadata exists and that it is of the proper type. Then to actually check the value, you call

arguments.stObject['bBool']

. Of course, since you want this to work no matter what the name of either property, everything has to be a variable!

What the code above does is check if ftWatch is defined, if it is, and the watched property is a boolean, AND if that boolean is 'false' (or '0' or 'no') or if the value has zero length (in case there is no ftDefault defined), then 'html' (which is returned as the thing to display) will be empty. For all other cases (such as ftWatch not being defined, the boolean being true, or the property not existing) the normal html will show.

The javascript is there to look up the entire row of the form and hide it from view, so that you don't have a label hanging out by itself! Neat, huh?

Of course, we could also put in a function call in addition to the javascript, and get all manner of fancy. But let's start simple, eh?