Whatever message this page gives is out now! Go check it out!
<cfparam
name = "parameter name"
default = "value"
max = "value"
maxLength = "number"
min = "value"
pattern = "regular expression"
type = "data_type">Attribute | Req/Opt | Default | Description |
name | Required | Name of the parameter (variable) to test (such as "Client.Email " or "Cookie.BackgroundColor "). If omitted, and if the parameter does not exist, an error is thrown. | |
default | Optional | Value to set parameter to if it does not exist. Any expression used for the default attribute is evaluated, even if the parameter exists. The result is not assigned if the parameter exists, but if the expression has side effects, they still occur. | |
max | Optional | The maximum valid value; used only for range validation. | |
maxLength | Optional | Used to specify the maximum character length of email, url, and string. | |
min | Optional | The minimum valid value; used only for range validation. | |
pattern | Optional | A JavaScript regular expression that the parameter must match; used only for regex or regular_expression validation. | |
type | Optional | any | The valid format for the data; one of the following. For detailed information on validation algorithms, see Validating form data using hidden fields in Validating data in the Developing ColdFusion Applications.
|
<!--- This example shows how to use CFPARAM to define default values for page variables. --->
<cfparam name = "storeTempVar" default = "my default value">
<cfparam name = "tempVar" default = "my default value">
<!--- Check if form.tempVar was passed. --->
<cfif IsDefined("form.tempVar") is "True">
<!--- Check if form.tempVar is not blank. --->
<cfif form.tempVar is not "">
<!--- If not, set tempVar to value of form.tempVar --->
<cfset tempVar = form.tempVar>
</cfif>
</cfif>
<body>
<h3>cfparam Example</h3>
<p>cfparam is used to set default values so that a developer does not have to
check for the existence of a variable using a function like IsDefined.</p>
<p>The default value of our tempVar is "<cfoutput>#StoreTempVar# </cfoutput>"</p>
<!--- Check if tempVar is still the same as StoreTempVar and that tempVar is not blank. --->
<cfif tempVar is not #StoreTempVar#
and tempVar is not "">
<h3>The value of tempVar has changed: the new value is
<cfoutput>#tempVar#</cfoutput></h3>
</cfif>
<p>
<form action = "cfparam.cfm" method = "post">
Type in a new value for tempVar, and hit submit:<br>
<input type = "Text" name = "tempVar">
<input type = "Submit" name = "" value = "submit">
</form><h1>Form Input Validation with Defaults Demo</h1>
<p><strong>What This Demo Shows:</strong> How to use cfparam to set defaults and validate form inputs.</p>
<hr>
<!--- Set default values for form fields using cfparam --->
<cfparam name="form.fullName" default="">
<cfparam name="form.email" default="">
<cfparam name="form.phone" default="">
<cfparam name="form.subject" default="General Inquiry">
<cfparam name="form.priority" default="Normal">
<cfparam name="form.message" default="">
<cfparam name="form.newsletter" default="false">
<h2>Example 1: Contact Form with Default Values</h2>
<cfif structKeyExists(form, "submit")>
<!--- Validate required fields with type checking --->
<cftry>
<!--- Ensure required fields exist and are not empty --->
<cfif len(trim(form.fullName)) EQ 0>
<cfthrow message="Full Name is required" type="ValidationError">
</cfif>
<cfif len(trim(form.email)) EQ 0>
<cfthrow message="Email is required" type="ValidationError">
</cfif>
<cfif len(trim(form.message)) EQ 0>
<cfthrow message="Message is required" type="ValidationError">
</cfif>
<!--- Basic email validation --->
<cfif NOT findNoCase("@", form.email) OR NOT findNoCase(".", form.email)>
<cfthrow message="Please enter a valid email address" type="ValidationError">
</cfif>
<div style="background-color: ##d4edda; border: 1px solid ##c3e6cb; padding: 15px; margin: 15px 0;">
<h3 style="color: ##155724; margin-top: 0;">✓ Form Submitted Successfully!</h3>
<cfoutput>
<p><strong>Name:</strong> #form.fullName#</p>
<p><strong>Email:</strong> #form.email#</p>
<p><strong>Phone:</strong> #len(form.phone) GT 0 ? form.phone : "(Not provided)"#</p>
<p><strong>Subject:</strong> #form.subject#</p>
<p><strong>Priority:</strong> #form.priority#</p>
<p><strong>Message:</strong> #form.message#</p>
<p><strong>Newsletter Opt-in:</strong> #form.newsletter EQ "true" ? "Yes" : "No"#</p>
</cfoutput>
</div>
<cfcatch type="ValidationError">
<div style="background-color: ##f8d7da; border: 1px solid ##f5c6cb; padding: 15px; margin: 15px 0;">
<h3 style="color: ##721c24; margin-top: 0;">✗ Validation Error</h3>
<cfoutput><p>#cfcatch.message#</p></cfoutput>
</div>
</cfcatch>
<cfcatch type="any">
<div style="background-color: ##f8d7da; border: 1px solid ##f5c6cb; padding: 15px; margin: 15px 0;">
<h3 style="color: ##721c24; margin-top: 0;">✗ Error</h3>
<cfoutput><p>#cfcatch.message#</p></cfoutput>
</div>
</cfcatch>
</cftry>
</cfif>
<form method="post">
<table cellpadding="8">
<tr>
<td><label>Full Name: <span style="color: red;">*</span></label></td>
<td><input type="text" name="fullName" value="<cfoutput>#form.fullName#</cfoutput>" size="40"></td>
</tr>
<tr>
<td><label>Email: <span style="color: red;">*</span></label></td>
<td><input type="text" name="email" value="<cfoutput>#form.email#</cfoutput>" size="40"></td>
</tr>
<tr>
<td><label>Phone: (optional)</label></td>
<td><input type="text" name="phone" value="<cfoutput>#form.phone#</cfoutput>" size="40"></td>
</tr>
<tr>
<td><label>Subject:</label></td>
<td>
<select name="subject">
<cfset subjects = ["General Inquiry", "Sales", "Support", "Feedback"]>
<cfloop array="#subjects#" index="subj">
<cfoutput>
<option value="#subj#" #form.subject EQ subj ? "selected" : ""#>#subj#</option>
</cfoutput>
</cfloop>
</select>
</td>
</tr>
<tr>
<td><label>Priority:</label></td>
<td>
<cfset priorities = ["Low", "Normal", "High", "Urgent"]>
<cfloop array="#priorities#" index="pri">
<cfoutput>
<input type="radio" name="priority" value="#pri#" #form.priority EQ pri ? "checked" : ""#> #pri#
</cfoutput>
</cfloop>
</td>
</tr>
<tr>
<td><label>Message: <span style="color: red;">*</span></label></td>
<td><textarea name="message" rows="5" cols="40"><cfoutput>#form.message#</cfoutput></textarea></td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" name="newsletter" value="true" <cfif form.newsletter EQ "true">checked</cfif>>
Subscribe to newsletter
</td>
</tr>
<tr>
<td colspan="2">
<button type="submit" name="submit">Submit Form</button>
</td>
</tr>
</table>
</form>
<hr>
<h2>Example 2: Default Values Demonstration</h2>
<!--- These cfparam tags demonstrate different default values --->
<cfparam name="url.testString" default="Default Text">
<cfparam name="url.testNumber" default="100">
<cfparam name="url.testBoolean" default="false">
<cfparam name="url.testList" default="apple,banana,orange">
<p><strong>Current Values (add URL parameters to change them):</strong></p>
<table border="1" cellpadding="8" cellspacing="0" style="border-collapse: collapse;">
<tr style="background-color: ##f0f0f0;">
<th>Parameter</th>
<th>Value</th>
<th>Default</th>
</tr>
<cfoutput>
<tr>
<td>url.testString</td>
<td>#url.testString#</td>
<td>Default Text</td>
</tr>
<tr>
<td>url.testNumber</td>
<td>#url.testNumber#</td>
<td>100</td>
</tr>
<tr>
<td>url.testBoolean</td>
<td>#url.testBoolean#</td>
<td>false</td>
</tr>
<tr>
<td>url.testList</td>
<td>#url.testList#</td>
<td>apple,banana,orange</td>
</tr>
</cfoutput>
</table>
<p><strong>Try it:</strong> <a href="?testString=Hello&testNumber=500&testBoolean=true&testList=cat,dog,bird">Click here to see custom values</a></p>
<hr><h1>URL Pagination Parameters Demo</h1>
<p><strong>What This Demo Shows:</strong> How to use cfparam to handle URL parameters for pagination and filtering.</p>
<hr>
<!--- Set default values for URL parameters --->
<cfparam name="url.page" default="1">
<cfparam name="url.perPage" default="10">
<cfparam name="url.sortBy" default="name">
<cfparam name="url.sortOrder" default="asc">
<cfparam name="url.category" default="all">
<!--- Validate and sanitize page number --->
<cftry>
<cfset url.page = val(url.page)>
<cfif url.page LT 1>
<cfset url.page = 1>
</cfif>
<cfcatch type="any">
<cfset url.page = 1>
</cfcatch>
</cftry>
<!--- Validate perPage --->
<cftry>
<cfset url.perPage = val(url.perPage)>
<cfif url.perPage LT 5 OR url.perPage GT 100>
<cfset url.perPage = 10>
</cfif>
<cfcatch type="any">
<cfset url.perPage = 10>
</cfcatch>
</cftry>
<!--- Create sample product data --->
<cfscript>
allProducts = [];
categories = ["Electronics", "Clothing", "Books", "Home", "Sports"];
for (i = 1; i LTE 47; i++) {
categoryIndex = ((i - 1) MOD 5) + 1;
arrayAppend(allProducts, {
id: i,
name: "Product " & i,
price: randRange(10, 500),
category: categories[categoryIndex]
});
}
// Filter by category
filteredProducts = [];
if (url.category NEQ "all") {
for (product in allProducts) {
if (product.category EQ url.category) {
arrayAppend(filteredProducts, product);
}
}
} else {
filteredProducts = allProducts;
}
// Sort products
if (url.sortBy EQ "name") {
filteredProducts.sort(function(a, b) {
if (url.sortOrder EQ "asc") {
return compare(a.name, b.name);
} else {
return compare(b.name, a.name);
}
});
} else if (url.sortBy EQ "price") {
filteredProducts.sort(function(a, b) {
if (url.sortOrder EQ "asc") {
return a.price - b.price;
} else {
return b.price - a.price;
}
});
}
// Calculate pagination
totalProducts = arrayLen(filteredProducts);
totalPages = ceiling(totalProducts / url.perPage);
// Ensure page is within range
if (url.page GT totalPages AND totalPages GT 0) {
url.page = totalPages;
}
startRow = ((url.page - 1) * url.perPage) + 1;
endRow = min(url.page * url.perPage, totalProducts);
// Get products for current page
pageProducts = [];
if (totalProducts GT 0) {
for (i = startRow; i LTE endRow; i++) {
arrayAppend(pageProducts, filteredProducts[i]);
}
}
</cfscript>
<h2>Product Listing with Pagination</h2>
<!--- Display current settings --->
<div style="background-color: ##f0f0f0; padding: 15px; margin: 15px 0;">
<cfoutput>
<p><strong>Current Settings:</strong></p>
<p>Page: #url.page# of #totalPages# | Items per page: #url.perPage# | Sort by: #url.sortBy# (#url.sortOrder#) | Category: #url.category#</p>
<p>Showing products #startRow# to #endRow# of #totalProducts# total</p>
</cfoutput>
</div>
<!--- Filter and Sort Controls --->
<form method="get" style="background-color: ##e3f2fd; padding: 15px; margin: 15px 0;">
<table>
<tr>
<td><label>Category:</label></td>
<td>
<select name="category">
<cfoutput>
<option value="all" #url.category EQ "all" ? "selected" : ""#>All Categories</option>
</cfoutput>
<cfloop array="#categories#" index="cat">
<cfoutput>
<option value="#cat#" #url.category EQ cat ? "selected" : ""#>#cat#</option>
</cfoutput>
</cfloop>
</select>
</td>
<td style="padding-left: 20px;"><label>Sort by:</label></td>
<td>
<select name="sortBy">
<cfoutput>
<option value="name" #url.sortBy EQ "name" ? "selected" : ""#>Name</option>
<option value="price" #url.sortBy EQ "price" ? "selected" : ""#>Price</option>
</cfoutput>
</select>
</td>
<td>
<select name="sortOrder">
<cfoutput>
<option value="asc" #url.sortOrder EQ "asc" ? "selected" : ""#>Ascending</option>
<option value="desc" #url.sortOrder EQ "desc" ? "selected" : ""#>Descending</option>
</cfoutput>
</select>
</td>
<td style="padding-left: 20px;"><label>Per Page:</label></td>
<td>
<select name="perPage">
<cfset perPageOptions = [5, 10, 20, 50]>
<cfloop array="#perPageOptions#" index="option">
<cfoutput>
<option value="#option#" #url.perPage EQ option ? "selected" : ""#>#option#</option>
</cfoutput>
</cfloop>
</select>
</td>
<td style="padding-left: 20px;">
<button type="submit">Apply</button>
</td>
</tr>
</table>
</form>
<!--- Product Grid --->
<table border="1" cellpadding="10" cellspacing="0" style="border-collapse: collapse; width: 100%;">
<tr style="background-color: ##0066cc; color: white;">
<th>ID</th>
<th>Product Name</th>
<th>Category</th>
<th style="text-align: right;">Price</th>
</tr>
<cfif arrayLen(pageProducts) GT 0>
<cfloop array="#pageProducts#" index="product">
<cfoutput>
<tr>
<td>#product.id#</td>
<td>#product.name#</td>
<td>#product.category#</td>
<td style="text-align: right;">$#numberFormat(product.price, "0.00")#</td>
</tr>
</cfoutput>
</cfloop>
<cfelse>
<tr>
<td colspan="4" style="text-align: center; padding: 20px;">No products found</td>
</tr>
</cfif>
</table>
<!--- Pagination Controls --->
<cfif totalPages GT 1>
<div style="margin: 20px 0; text-align: center;">
<cfoutput>
<!--- Previous button --->
<cfif url.page GT 1>
<a href="?page=#url.page - 1#&perPage=#url.perPage#&sortBy=#url.sortBy#&sortOrder=#url.sortOrder#&category=#url.category#" style="padding: 5px 10px; background-color: ##0066cc; color: white; text-decoration: none;">« Previous</a>
<cfelse>
<span style="padding: 5px 10px; background-color: ##ccc; color: ##666;">« Previous</span>
</cfif>
<!--- Page numbers --->
<cfloop from="1" to="#totalPages#" index="pageNum">
<cfif pageNum EQ url.page>
<strong style="padding: 5px 10px; background-color: ##0066cc; color: white;">#pageNum#</strong>
<cfelse>
<a href="?page=#pageNum#&perPage=#url.perPage#&sortBy=#url.sortBy#&sortOrder=#url.sortOrder#&category=#url.category#" style="padding: 5px 10px; text-decoration: none; border: 1px solid ##ddd;">#pageNum#</a>
</cfif>
</cfloop>
<!--- Next button --->
<cfif url.page LT totalPages>
<a href="?page=#url.page + 1#&perPage=#url.perPage#&sortBy=#url.sortBy#&sortOrder=#url.sortOrder#&category=#url.category#" style="padding: 5px 10px; background-color: ##0066cc; color: white; text-decoration: none;">Next »</a>
<cfelse>
<span style="padding: 5px 10px; background-color: ##ccc; color: ##666;">Next »</span>
</cfif>
</cfoutput>
</div>
</cfif>
<hr>
<h2>Try Different URLs:</h2>
<ul>
<li><a href="?page=1&perPage=5">5 items per page</a></li>
<li><a href="?page=2&perPage=10">Page 2 with 10 items</a></li>
<li><a href="?sortBy=price&sortOrder=desc">Sort by price descending</a></li>
<li><a href="?category=Electronics">Electronics only</a></li>
<li><a href="?category=Books&sortBy=name&sortOrder=asc">Books sorted by name</a></li>
<li><a href="?page=99">Invalid page number (auto-corrects)</a></li>
</ul>
<hr><h1>Search Filter Management Demo</h1>
<p><strong>What This Demo Shows:</strong> How to use cfparam to manage multiple search filters with defaults.</p>
<hr>
<!--- Set default values for all search/filter parameters --->
<cfparam name="url.keyword" default="">
<cfparam name="url.category" default="all">
<cfparam name="url.minPrice" default="0">
<cfparam name="url.maxPrice" default="1000">
<cfparam name="url.minRating" default="0">
<cfparam name="url.inStock" default="false">
<cfparam name="url.onSale" default="false">
<cfparam name="url.sortBy" default="relevance">
<!--- Validate numeric parameters --->
<cfset url.minPrice = val(url.minPrice)>
<cfset url.maxPrice = val(url.maxPrice)>
<cfset url.minRating = val(url.minRating)>
<!--- Ensure min/max are in correct order --->
<cfif url.minPrice GT url.maxPrice>
<cfset temp = url.minPrice>
<cfset url.minPrice = url.maxPrice>
<cfset url.maxPrice = temp>
</cfif>
<!--- Create sample product data --->
<cfscript>
allProducts = [
{name: "Laptop Pro 15", category: "Electronics", price: 899, rating: 4.5, inStock: true, onSale: false},
{name: "Wireless Mouse", category: "Electronics", price: 29, rating: 4.0, inStock: true, onSale: true},
{name: "Office Chair", category: "Furniture", price: 199, rating: 4.2, inStock: true, onSale: false},
{name: "Standing Desk", category: "Furniture", price: 449, rating: 4.8, inStock: false, onSale: false},
{name: "USB-C Cable", category: "Electronics", price: 12, rating: 3.5, inStock: true, onSale: true},
{name: "Monitor 27in", category: "Electronics", price: 349, rating: 4.6, inStock: true, onSale: false},
{name: "Keyboard Mechanical", category: "Electronics", price: 89, rating: 4.3, inStock: true, onSale: true},
{name: "Desk Lamp", category: "Furniture", price: 45, rating: 4.1, inStock: true, onSale: false},
{name: "Bookshelf", category: "Furniture", price: 129, rating: 3.9, inStock: false, onSale: false},
{name: "Webcam HD", category: "Electronics", price: 79, rating: 4.4, inStock: true, onSale: true},
{name: "Filing Cabinet", category: "Furniture", price: 159, rating: 4.0, inStock: true, onSale: false},
{name: "Headphones", category: "Electronics", price: 149, rating: 4.7, inStock: true, onSale: false}
];
// Apply filters
filteredProducts = [];
for (product in allProducts) {
matchesFilters = true;
// Keyword search
if (len(trim(url.keyword)) GT 0) {
if (NOT findNoCase(url.keyword, product.name)) {
matchesFilters = false;
}
}
// Category filter
if (url.category NEQ "all" AND product.category NEQ url.category) {
matchesFilters = false;
}
// Price range filter
if (product.price LT url.minPrice OR product.price GT url.maxPrice) {
matchesFilters = false;
}
// Rating filter
if (product.rating LT url.minRating) {
matchesFilters = false;
}
// In stock filter
if (url.inStock EQ "true" AND NOT product.inStock) {
matchesFilters = false;
}
// On sale filter
if (url.onSale EQ "true" AND NOT product.onSale) {
matchesFilters = false;
}
if (matchesFilters) {
arrayAppend(filteredProducts, product);
}
}
// Sort results
if (url.sortBy EQ "price_asc") {
filteredProducts.sort(function(a, b) { return a.price - b.price; });
} else if (url.sortBy EQ "price_desc") {
filteredProducts.sort(function(a, b) { return b.price - a.price; });
} else if (url.sortBy EQ "rating") {
filteredProducts.sort(function(a, b) { return b.rating - a.rating; });
}
totalResults = arrayLen(filteredProducts);
</cfscript>
<h2>Product Search</h2>
<!--- Search Form --->
<form method="get" style="background-color: ##f0f0f0; padding: 20px; margin: 15px 0;">
<table cellpadding="8">
<tr>
<td><label><strong>Keyword:</strong></label></td>
<td colspan="3">
<input type="text" name="keyword" value="<cfoutput>#url.keyword#</cfoutput>" size="40" placeholder="Search products...">
</td>
</tr>
<tr>
<td><label><strong>Category:</strong></label></td>
<td>
<select name="category">
<cfoutput>
<option value="all" #url.category EQ "all" ? "selected" : ""#>All Categories</option>
<option value="Electronics" #url.category EQ "Electronics" ? "selected" : ""#>Electronics</option>
<option value="Furniture" #url.category EQ "Furniture" ? "selected" : ""#>Furniture</option>
</cfoutput>
</select>
</td>
<td><label><strong>Sort by:</strong></label></td>
<td>
<select name="sortBy">
<cfoutput>
<option value="relevance" #url.sortBy EQ "relevance" ? "selected" : ""#>Relevance</option>
<option value="price_asc" #url.sortBy EQ "price_asc" ? "selected" : ""#>Price: Low to High</option>
<option value="price_desc" #url.sortBy EQ "price_desc" ? "selected" : ""#>Price: High to Low</option>
<option value="rating" #url.sortBy EQ "rating" ? "selected" : ""#>Rating</option>
</cfoutput>
</select>
</td>
</tr>
<tr>
<td><label><strong>Price Range:</strong></label></td>
<td colspan="3">
<cfoutput>
$<input type="text" name="minPrice" value="#url.minPrice#" size="6"> to
$<input type="text" name="maxPrice" value="#url.maxPrice#" size="6">
</cfoutput>
</td>
</tr>
<tr>
<td><label><strong>Min Rating:</strong></label></td>
<td>
<select name="minRating">
<cfloop from="0" to="4" index="rating">
<cfoutput>
<option value="#rating#" #url.minRating EQ rating ? "selected" : ""#>
#rating GT 0 ? rating & "+ Stars" : "Any"#
</option>
</cfoutput>
</cfloop>
</select>
</td>
<td colspan="2">
<cfoutput>
<input type="checkbox" name="inStock" value="true" #url.inStock EQ "true" ? "checked" : ""#> In Stock Only
<input type="checkbox" name="onSale" value="true" #url.onSale EQ "true" ? "checked" : ""#> On Sale Only
</cfoutput>
</td>
</tr>
<tr>
<td colspan="4">
<button type="submit" style="padding: 8px 20px;">Search</button>
<a href="?" style="padding: 8px 20px; background-color: ##ccc; color: ##333; text-decoration: none; display: inline-block;">Clear Filters</a>
</td>
</tr>
</table>
</form>
<!--- Active Filters Display --->
<cfif len(url.keyword) GT 0 OR url.category NEQ "all" OR url.minPrice GT 0 OR url.maxPrice LT 1000 OR url.minRating GT 0 OR url.inStock EQ "true" OR url.onSale EQ "true">
<div style="background-color: ##fff3cd; padding: 10px; margin: 15px 0; border-left: 4px solid ##ff9800;">
<strong>Active Filters:</strong>
<cfoutput>
<cfif len(url.keyword) GT 0><span style="background-color: white; padding: 3px 8px; margin: 2px; border: 1px solid ##ddd;">Keyword: "#url.keyword#"</span></cfif>
<cfif url.category NEQ "all"><span style="background-color: white; padding: 3px 8px; margin: 2px; border: 1px solid ##ddd;">Category: #url.category#</span></cfif>
<cfif url.minPrice GT 0 OR url.maxPrice LT 1000><span style="background-color: white; padding: 3px 8px; margin: 2px; border: 1px solid ##ddd;">Price: $#url.minPrice# - $#url.maxPrice#</span></cfif>
<cfif url.minRating GT 0><span style="background-color: white; padding: 3px 8px; margin: 2px; border: 1px solid ##ddd;">Rating: #url.minRating#+ Stars</span></cfif>
<cfif url.inStock EQ "true"><span style="background-color: white; padding: 3px 8px; margin: 2px; border: 1px solid ##ddd;">In Stock</span></cfif>
<cfif url.onSale EQ "true"><span style="background-color: white; padding: 3px 8px; margin: 2px; border: 1px solid ##ddd;">On Sale</span></cfif>
</cfoutput>
</div>
</cfif>
<!--- Results Count --->
<p><cfoutput><strong>Found #totalResults# product<cfif totalResults NEQ 1>s</cfif></strong></cfoutput></p>
<!--- Results Grid --->
<table border="1" cellpadding="10" cellspacing="0" style="border-collapse: collapse; width: 100%;">
<tr style="background-color: ##0066cc; color: white;">
<th>Product</th>
<th>Category</th>
<th style="text-align: right;">Price</th>
<th style="text-align: center;">Rating</th>
<th style="text-align: center;">Status</th>
</tr>
<cfif totalResults GT 0>
<cfloop array="#filteredProducts#" index="product">
<cfoutput>
<tr>
<td>
#product.name#
<cfif product.onSale><span style="background-color: ##ff5722; color: white; padding: 2px 6px; font-size: 10px; margin-left: 5px;">SALE</span></cfif>
</td>
<td>#product.category#</td>
<td style="text-align: right;">$#numberFormat(product.price, "0.00")#</td>
<td style="text-align: center;">#product.rating# ⭐</td>
<td style="text-align: center;">
<cfif product.inStock>
<span style="color: ##2e7d32;">✓ In Stock</span>
<cfelse>
<span style="color: ##c62828;">✗ Out of Stock</span>
</cfif>
</td>
</tr>
</cfoutput>
</cfloop>
<cfelse>
<tr>
<td colspan="5" style="text-align: center; padding: 30px; color: ##666;">
No products match your search criteria. Try adjusting your filters.
</td>
</tr>
</cfif>
</table>
<hr>
<h2>Quick Filter Examples:</h2>
<ul>
<li><a href="?category=Electronics">Electronics only</a></li>
<li><a href="?minPrice=100&maxPrice=500">Price range $100-$500</a></li>
<li><a href="?minRating=4">4+ star ratings</a></li>
<li><a href="?inStock=true">In stock products</a></li>
<li><a href="?onSale=true">On sale items</a></li>
<li><a href="?keyword=mouse&category=Electronics&inStock=true">Keyword + multiple filters</a></li>
</ul>
<hr>