can a filter help me achieve something like this?

3 views
Skip to first unread message

jarthel

unread,
Oct 29, 2009, 3:43:38 AM10/29/09
to Mach-II for CFML
e.g. click on a link that's suppose to do display the record details.
used listener to retrieve the multiple parts (e.g. a complete record
is made up of records from different tables). BUT when I was getting
the record for table3, something happen (Oracle error, SQL syntax
error and etc).

I know filter can return false to stop its execute but am I able:
1. to return something to the original page (i.e. page that has the
link that I clicked). I need a return value so that I know something
happened so I can display a message.

2. I suppose I can retrieve records (accessing my "service" CFCs) in
filters?

Thank you very much

Adrian Scott

unread,
Oct 29, 2009, 2:03:49 PM10/29/09
to Mach-II for CFML
Yes, filters are exactly for what you're asking for.

I'm an advocate of creating an errorBean of some kind that stores a
structure of errors, keyed to the names of the input elements that may
cause the error. I typically like to instantiate this errorBean
object in my plugin so that it exists on all pages, then within my
view I'd check to see if there is an error with a particular key (e.g.
you have an input named 'startDate' so you'd check your errorBean for
this value and display the message you've provided directly next to
the input field).

So, in your filter, you can run a check to see if things will process
successfully, and then add the errors you've found into this
errorBean. At the end of your filter, check to see if there are
errors in the error bean, and if there are, re-announce the previous
event (call announceEvent and include the event args so that the
errorBean persists) and return false to stop processing of the current
event.

Adrian.

Adrian Scott

unread,
Oct 30, 2009, 2:14:29 PM10/30/09
to Mach-II for CFML
To illustrate an "errorBean" a little further (since I received a few
requests as to how this can be accomplished) I'll include an example
below...

<cfcomponent name="ErrorBean" output="false">

<!--- create an errors structure --->
<cfset variables.errors = StructNew() />

<cffunction name="addError" access="public" output="false"
returntype="void" hint="Adds a new error to the error structure">
<cfargument name="name" required="true" type="string" hint="Name
of the error; best practice to use form name here" />
<cfargument name="message" required="true" type="string"
hint="Message regarding this error" />
<cfset variables.errors[arguments.name] = arguments.message />
</cffunction>

<cffunction name="getError" access="public" output="false"
returntype="string" hint="Returns an error from the error structure">
<cfargument name="name" required="true" type="string" hint="Name
of the error to return; if error doesn't exist, returns empty string" /
>
<cfif hasError(arguments.name)>
<cfreturn variables.errors[arguments.name] />
<cfelse>
<cfreturn '' />
</cfif>
</cffunction>

<cffunction name="hasError" access="public" output="false"
returntype="boolean" hint="Returns true if the error exists within the
error structure">
<cfargument name="name" required="true" type="string" hint="Name
of the error to check" />
<cfreturn StructKeyExists(variables.errors, arguments.name) />
</cffunction>

<cffunction name="hasErrors" access="public" output="false"
returntype="boolean" hint="Returns true if there is at least one
error">
<cfreturn NOT StructIsEmpty(variables.errors) />
</cffunction>

</cfcomponent>

My recommendation is to instantiate the ErrorBean in the plugin, then
when your filters run, your ErrorBean will exist within the Event
scope. When you're doing form-field validation, as an example, you
can put any errors you find within the ErrorBean so that you can
report the issues back to the users in a contextual fashion.

In your filter whilst doing validation:

<cfset var errorBean = arguments.event.getArg('errorBean') />

<cfif NOT Len(arguments.event.getArg('firstName')>
<cfset errorBean.addError('firstName', 'You must provide a first
name!') />
</cfif>

Then at the end of your filter you can:

<cfif errorBean.hasErrors()>
<cfset announceEvent('TheEventIOriginallyCameFrom') />
<cfreturn false />
</cfif>

And to display the error message next to the input field it originated
from, in your view you can:

<cfset errorBean = request.event.getArg('errorBean') />
...
<cfif errorBean.hasError('firstName')>
<div class="error">#errorBean.getError('firstName')#</div>
</cfif>
<input type="text" name="firstName" value="#request.event.getArg
('firstName')#" />

This is, of course, one of many possible ways to utilize filters and
plugins to report issues back to the user as well as change the flow
of the event. If you have any questions, feel free to respond to this
thread so that all can see them!

Adrian.

Adrian Scott

unread,
Oct 30, 2009, 2:19:11 PM10/30/09
to Mach-II for CFML
Crap, the part "Then at the end of your filter" should have:

<cfset announceEvent('TheEventIOriginallyCameFrom',
arguments.event.getArgs()) />

Since you need to pass the event arguments to the next event (so that
the ErrorBean and the errors within get carried over).

Adrian.

Peter J. Farrell

unread,
Oct 30, 2009, 2:58:58 PM10/30/09
to mach-ii-for...@googlegroups.com
Adrian Scott said the following on 10/30/2009 01:19 PM:
> <cfset announceEvent('TheEventIOriginallyCameFrom',arguments.event.getArgs()) />
>

Or as part of the Mach-II Simplicity (this is the BER, not the Beta1
released in August), you can use a nifty shortcut:

<cfset announceEvent('TheEventIOriginallyCameFrom', arguments.event) />


Passing in the entire event with arguments.event is equal to
arguments.event.getArgs(). The framework will now call getArgs() for you.

Best,
.Peter

Reply all
Reply to author
Forward
0 new messages