As stated earlier, the custom tag that you created can take any three numbers and multiply them. The tag will then return the result of that multiplication to the template that called it. This is fine by itself but pretty limiting. The Multiply custom tag must be sent three, and only three numbers. If anything more or less is sent, the tag will throw an error
To create a trulypowerful tag, it would be beneficial if your custom tag could take any number of attributes. Tofacilitate this modification, make some basic changes to your custom tag. Instead of sending NUM1 NUM2 and NUM3 send an attribute called NUMBERST his attribute will be a list of numbers that the tag will multiply. This way any number of figures may be sent to the tag. You begin by changing your calling document. Listing 31.4 shows the code changes to reflect the new attribute
The change dline <CF _ Multiply New NUMBERS = ” # Form . Number1# #Form.Number2# #Form. Number3#”>, represents the change you are going to make to ~ur custom tag. As stated previously you are going to send a list of numbers to your custom tag. In this case your list is comprised of the three form variables from your application. You will also notice that you are going to use a new custom tag, aptly named Multiply New.This is simply done so that you can compare the versions. Listing 31.5 shows the new version of your custom tag.
ThiS ability to return results to different variables in the calling template is not something you have to do in a custom tag; again, it’s just a nice feature to have.
The next line, <CFSET Fi na’l Resu’l t – ‘1>, will be used by your tag to keep the current result. As you multiply each-set of numbers, you need a-way to store the total number. Because every number multiplied by 1is equal to itself, setting Final Result to 1 has no effect on your result.
The next block of code beginning with <CFIF NOTIsDefi ned(‘ Attri butes . Numbers’» and ending with </CF,IF> makes sure that the calling template sends the Numbers attribute. Remember that each custom tag has different kinds of attributes required not required and conditionally required. In this instance you make Numbers a required attribute. If the ‘user does not send the attribute you display a simple error message and then use the CFABORTtag to end execution
Note that there are two ways of leaving a custom tag:’ You can use CFEXITor CFABORT_. If you use CFooT, the custom tag will stop executing but will not stop the calling tem- ‘ _ plate. In this case you use CFABORTbecauseyou assume that if the calling template has . , made this mistake, everything else should stop. In other cases, you may need to alter- , nate between using CFEXITand Cj:~BORTdepending on the nature of particular custom tags and the nature of the errors you are encountering.
After determining that the user has sent all’the required attributes (in this case only one), next you need to make sure that the attributes sent ate of the correct type. This will change from tag to tag but in this case, you want to ensure that the Numbers attribute is a list. You could use many techniques to achieve this, including the following:
• Check for the comma delimiter by using the Find function
• Use, the i..i sten function to make sure you have at least two items
But each of those methods is not exactly what you want. In both cases you are assuming that your 1iS~will have at least’ t.’v0 elements. But what if you want your tag to be handle lists with a single element as well? Then neither approach is the perfect solution.
In your custom tag, you haven’t done a detailed analysis of the list of numbers being passed to the tag. Instead you have done a simple test: you check whether the data
passed in the Numbers attribute is a simple string (as opposed to a more complex data ” type such as an array). You do this with the Is,Si mple Value function. If there is an error the CFABORTtag provides the means to halt execution and display an error message.
Next comes the heart of the tag. If you reach this point, you know that you have the .proper attribute and that it is a simple string you can treat as a list. You use the following line to loop through the Numbers attribute:
<CFLOOP INDEX-‘CURR_NUMBER’ LIST-“Attributes,Numbers”>
As you can see, you have told the CFLOOPtag to use Attri butes. Numberas the list and CURR_NUMBaEsRthe index. The index, CURR_NUMBEwRil,l be set to the current number as you loop through the list. Inside the loop, you do some more simple error checking. For each item in the list, which you can access via the variable CURR_NUMBEyoRu, check to make sure it is a valid number. The following code sample shows that check in action
<CFIF NOT IsNumeric(CURR_NUMBER»
<CFOUTPUT><B>MultiplyNew Error</B> – ‘CURR_NUMBER’, which was sent to the
tag, is not a valid number.</CFOUTPUT>
The Is Numeric function is a quick and simple way to do that. Again, if you encounter a problem with the data, you throw an error message to the user and CFABORTout of the tag. Also note that when you send the error message, you specifically tell the user which item is invalid.
If the current item is a valid number, you simply update. your Fi na 1Resul t variable by multiplying by CURR_NUMBEasR,follows:
<CFSET FinalResult – FinalResult •.CURR_NUMBER>
As a side note, if any number in the list is zero, the Fi na 1Resul t variable will equal zero and will not change. This is the standard rule of multiplication: any value multiplied by zero results in zero (If you want, you could use the Li stContai ns function to search for zero and not even bother with the loop. This would speed things up if you
had the possibility of multiplying hundreds of numbers together.)
The final step is to return the result to the calling template. As discussed earlier the variable that is created in the calling template is dynamic. If the user does not specify a Retu rn attribute, the custom tag will use the name RESULTfor the variable. If the user sets the Return attribute that name will be used instead. The following line shows Cold-Fusion’s method of handling dynamic variables
<CFSET ‘Caller.#Attributes.Return#’ – FinalResult>
As you can see to create a dynamic variable in ColdFusion you can simply wrap the variable name in quotes. In this case if the user does not set a Return attribute and it defaults to RESULT,y~Llcan imagine the previous line as reading <CFSET Call e r ‘. . RESULT- Fi na1Resu1 t>. Remember that this is not necessary, but it’s a nice feature to add to your tag.
Now that you have built your custom tag, you can send any number of figures to the tag. Listing 31.6 is a modification of your previous template. This time you are sending five numbers to the custom tag
<CFPARAM NAME-‘Form.Numberl’ DEFAULT-l>
<CFPARAM NAME-‘Form.Number2’ DEFAULT-l>
.<CFPARAM NAME-‘Form.Number3’ DEFAULT-l>
<CFPARAM NAME-‘Form.Number4′ DEFAULT-l>
<CFPARAM NAME-·Form.NumberS’ DEFAULTzl>
<CFOUTPUT>The result of your multiplication of #Val(Form.Numberl)#,
#Val(Form.Number2)#, #Val(Form.Number3)#, #Val(Form.Number4)#, and
#Val(Form.NumberS)# is #RESULT#</CFOUTPUT>
<FORM ACTION-‘MultiplyFive.crm’ METHOO=”POST”>
<TD><INPUT TYPE-‘text’ NAME-‘Numberl’ SIZE=3 VALUEz’# al(Form.Numberl)#’></TD>
<TD><INPUT TYPE-‘text’ NAME-‘Number2, S~ZE·3 VALUE-‘~Val(Form.Number2)~’></TD>
<TO><INPUT TYPE=’text’ NA~E=’Number3′ SIZE~3 VALUE=’#Val(Form.Number3)#’></TO>
<TO><INPUT TYPE=’text’ NAME=”Number4′ SIZE~3 VALUE=’#Val(Form.Number4)#’></TO>
<TD><INPUT TYPE-‘text’ NAME=’NumberS’ SIZE=< VALUE=’#Val(Form.NumberS)#’></TO>
<TO COLSPAN=2><INPUT TYPE=’Subm-it” VALUE=”Oisplay Result’></TD>
The modifications to your calling template are minor. You simply added extra form fields and CFPARAMfosr the form fields. You then passed the new form fields to the Multiply New custom tag. This tag ~asily handled the new numbers and returned the results to the template.