FormValidation Screencast 2

January 16th, 2007

Now you can watch a more lightweight version in Flash. Keep the questions coming.

Thanks to Jay for pointing me to Camtasia, they deserve the $299 per license.

29 Responses to “FormValidation Screencast 2”

Chad Humphries Says:

Try wink (http://www.debugmode.com/wink/) sometime, it’s 100% free and has worked great for all of my screencasting in swf

Dan Bunea Says:

Camtasia is commercial, we are using Debugmode Wink, which is open source and works great.

Thanks,

makka Says:

Validazione con MonoRail

zuppaman Says:

Maybe its an option to upload it on video.google.com in multiple parts.
At this moment the video takes forever to load…

Ernst Says:

download this screencast via BitTorrent; http://www.mininova.org/tor/549049

goodwill Says:

Darn cool! Would that also work with ActiveRecordValidationBase?

goodwill Says:

I found it is not working yet already :(
A question though- I found the form tag is only building a static form, which would not work if I need an ajax form, I guess thats an outstanding feature or I missed something?

goodwill Says:

By the way, I read thru the Really easy field validation… I think you might want to see if there are alternatives which provides more flexibility, something like what fValidate provides? fValidate is not pretty (as oppose to Really easy field), but it does provide easier to localize scripts, and more flexible date format etc

hammett Says:
goodwill Says:

Cool! How about making $Form works for ajax form?

hammett Says:

How about sending a patch? :-)

goodwill Says:

Haha… I am not using Validator yet unfortunately. A question- if except from the fact it wouldn’t trigger from ActiveRecordValidationBase, that indeed would be able to validate the attribute properly if I applied these validator attrib. to my AR class and use SmartDispatcher, correct? I still haven’t got an idea on how to put it to work in AR though, I think that is more a priority.

rodney Says:

Ok, this is awesome.

I have specified a default error message like this:


ValidateNonEmpty("Campaign Title is Required!")

However, I noticed that the error message is never displayed on the client side. Is this just not implemented yet or am I misunderstanding how the error message is intended to be used?

hammett Says:

Are you using useTitles=’true’ on the FormTag() ?

rodney Says:

Yes, my form tag looks like this:


$Form.FormTag("%{action='insertcampaign', enctype='multipart/form-data', immediate='true', useTitles='true', stopOnFirst='false', focusOnError='true'}")

hammett Says:

Can you confirm that the input element has an attribute title with the desired error message?

rodney Says:

Hammett, thanks for your help. Unfortunately, my debugger in Visual Studio isn’t working. Otherwise, I would debug it and send you a patch.

I am using Revision 3317.

Below is the code for the class that I am using:


namespace HM.ARS.Base {
using System.Collections;
using Castle.ActiveRecord;
using Castle.Components.Validator;
using ValidateLengthAttribute=Castle.Components.Validator.ValidateLengthAttribute;

[ActiveRecord("campaign")]
public class Campaign : ActiveRecordBase {
private string _title;
private int _id;
private IList _campaignCategories = new ArrayList();
//private byte[] _wordDocument;
//private byte[] _image;
private string _brand;
private Submitter _submitter;
private string _clientName;
private Event _event;
private Agency _agency;
private IList _categories;
private string _imageName;
private string _wordDocName;
private bool _paid;
private string _entryCode;

public Campaign() {}

public Campaign(int id) {
_id = id;
}

public Campaign(string title) {
_title = title;
}

public Campaign(string title, int id) {
_title = title;
_id = id;
}

[PrimaryKey]
public virtual int Id { get { return _id; } set { _id = value; } }

[BelongsTo("submitter_id")]
public virtual Submitter Submitter { get { return _submitter; } set { _submitter = value; } }

[Property("title"), ValidateNonEmpty("Campaign Title is Required!"), ValidateLength(2, 200, "Please enter between 2 and 200 Characters!")]
public virtual string Title { get { return _title; } set { _title = value; } }

[Property("brand"), ValidateNonEmpty("Campaign Brand is Required")]
public virtual string Brand { get { return _brand; } set { _brand = value; } }

[BelongsTo("event_id")]
public virtual Event Event { get { return _event; } set { _event = value; } }

[Property("client_name"), ValidateNonEmpty("Campaign Client Name is Required!")]
public virtual string ClientName { get { return _clientName; } set { _clientName = value; } }

[Property("image_name")]
public string ImageName { get { return _imageName; } set { _imageName = value; } }

[Property("word_doc_name")]
public string WordDocName { get { return _wordDocName; } set { _wordDocName = value; } }

[BelongsTo("agency_id")]
public virtual Agency Agency { get { return _agency; } set { _agency = value; } }

[Property("paid")]
public bool Paid { get { return _paid; } set { _paid = value; } }

[HasMany(typeof (CategoryCampaign),
Table="category_campaign", ColumnKey="campaign_id",
Inverse=false, Cascade=ManyRelationCascadeEnum.AllDeleteOrphan)]
public virtual IList CampaignCategories { get { return _campaignCategories; } set { _campaignCategories = value; } }

public void AddCategory(Category category) {
CategoryCampaign categorycampaign = new CategoryCampaign(this, category);
if (!CampaignCategories.Contains(categorycampaign)) CampaignCategories.Add(categorycampaign);
}

public void DeleteCategory(Category category) {
CategoryCampaign categorycampaign = new CategoryCampaign(this, category);
if (CampaignCategories.Contains(categorycampaign)) CampaignCategories.Remove(categorycampaign);
}

public IList Categories {
get {
if (_categories != null)
return _categories;

IList categories = new ArrayList();
foreach (CategoryCampaign cc in _campaignCategories) categories.Add(cc.Category);

_categories = categories;
return _categories;
}

set { foreach (Category category in value) AddCategory(category); }
}

[Property("entry_code")]
public string EntryCode { get { return _entryCode; } set { _entryCode = value; } }

public void RemoveAllCategories() {
foreach (Category cat in Categories) DeleteCategory(cat);
}

public override string ToString() {
return string.Format("Campaign Id: {0}, Title: {1}, Brand: {2}, Agency: {3}", Id, Title, Brand, Agency);
}
}
}

Here is the new action:


public void NewCampaign() {
PropertyBag["usertype"] = typeof (Campaign);

Submitter submitter = MemberUtil.GetSubmitter();

//this should rarely happen but is here just in case it does.
if (submitter == null) {
Flash["error"] = "Your username was not found and therefore you will not be able to continue!";
Redirect("~/login/index.rails");
}

String[] states = StringUtil.GetStates();

Campaign campaign = new Campaign();
campaign.Agency = Agency.Find(ConvertUtil.ConvertInteger(Request["agency.id"]));
campaign.Submitter = submitter;

PropertyBag.Add("campaign", campaign);
PropertyBag["categories"] = Category.FindRootCategories();

PropertyBag["states"] = states;

if (submitter != null) {
IList campaigns;
campaigns = Campaign.FindAllByProperty("Submitter", submitter);

campaigns = campaigns.Count > 0 ? campaigns : null;

PropertyBag["campaigns"] = campaigns;
}
}

Here is the Insert Action:


public void NewCampaign() {
PropertyBag["usertype"] = typeof (Campaign);

Submitter submitter = MemberUtil.GetSubmitter();

//this should rarely happen but is here just in case it does.
if (submitter == null) {
Flash["error"] = "Your username was not found and therefore you will not be able to continue!";
Redirect("~/login/index.rails");
}

String[] states = StringUtil.GetStates();

Campaign campaign = new Campaign();
campaign.Agency = Agency.Find(ConvertUtil.ConvertInteger(Request["agency.id"]));
campaign.Submitter = submitter;

PropertyBag.Add("campaign", campaign);
PropertyBag["categories"] = Category.FindRootCategories();

PropertyBag["states"] = states;

if (submitter != null) {
IList campaigns;
campaigns = Campaign.FindAllByProperty("Submitter", submitter);

campaigns = campaigns.Count > 0 ? campaigns : null;

PropertyBag["campaigns"] = campaigns;
}
}

Here is the form:

Use the following form to add a new campaign
 #if($Flash.error)

Errors: $Flash.error

#end
$Form.FormTag("%{action='insertcampaign', enctype='multipart/form-data', immediate='true', useTitles='true', stopOnFirst='false', focusOnError='true'}")
$Form.HiddenField("campaign.submitter.id")
$Form.HiddenField("campaign.agency.id")

Campaign Info

$Form.LabelFor("campaign.title", "Campaign Title:") $Form.TextField("campaign.title", "%{class='textentry'}")

$Form.LabelFor("campaign.clientname", "Client:") $Form.TextField("campaign.clientname", "%{class='textentry'}")

$Form.LabelFor("campaign.brand", "Brand:") $Form.TextField("campaign.brand", "%{class='textentry'}")

Attach Doc: $HtmlHelper.InputFile("doc", "%{style='width:300px;'}")

Attach PSD: $HtmlHelper.InputFile("image", "%{style='width:300px;'}")

Categories

#foreach($elem in $categories)
#if($elem.SubCategories)
$elem.DisplayName
#set($items = $Form.CreateCheckboxList("newcategories", $elem.SubCategories, "%{value='Id', class='checkbox'}"))

#foreach($cat in $items)
$items.Item() $cat.DisplayName
#end
#end
#end

Next >
$Form.Submit("Save And Continue", "%{id='savecontinue', name='savecontinue', class='submitbutton'}")
$Form.Submit("Add Another", "%{id='addanother', name='addanother', class='submitbutton'}")

$Form.EndFormTag()

Here is the browser output from IE 6:

Use the following form to add a new campaign
 

Campaign Info

Campaign Title:

Client:

Brand:

Attach Doc:

Attach PSD:

Categories

Media Planning and Buying Awards

Best Campaign in Professional Media
Best Campaign in Consumer Media

Next >

new Validation('form1', {onSubmit:true, focusOnError:true, stopOnFirst:false, immediate:true, useTitles:true});

hammett Says:

Please, don’t post such big message again. It’s useless as wordpress strips everything.

I just asked to check for the presence of the title attribute on the element, it would be easier to just say ‘no, it isn’t there’, or ‘yes, I can see them’.

Now I’d suggest that you take this question to Castle forum anyway.

rodney Says:

I am sorry hammett. I will not do that again. I misunderstood what you were asking for and thought that would be the most useful.

Rhywun Says:

I’m *so* close to getting the client validation working. It helped that I figured out you need to add $Form.InstallScripts() which wasn’t shown in the video. Anyway for some reason I have to submit the page twice to get the client script to show the error messages. My form tag looks like this:
$Form.FormTag(“%{action=’Create’, immediate=’true’, useTitles=’true’}”)
And the input tags do not show the class or title attributes until I submit the form one time.

hammett Says:

I’ll upload a sample project shortly.

Rhywun Says:

Yay!

Zen and the art of Castle maintenance » Archives » Web Client Software Factory vs MonoRail Says:

[...] – Validation: Castle has the Castle.Component.Validator, and MonoRail is fully integrated to it. This screencast might explain it a little better. [...]

joeyDotNet Says:

Castle MonoRail & ActiveRecord – First Impressions

Beauty = Monorail + Validation + Active Record + (IE * Grief) « Adam Tybor’s Blog : Abstract && Concrete Says:

[...] Posted on April 10th, 2007. So I started playing with monorail today. It’s a very intelligent platform that I will continue to blog about. I got a sample setup very quickly thanks to Ayende’s screen cast. The next step I wanted to play with was validation. Hamilton Verissimo has a nice screen cast showing off the new functionality with javascript agnostic code. Very cool that MR insulates you from a particular javascript library. [...]

Beauty = Monorail + Validation + Active Record + (IE * Grief) | Adam Tybor's Blog Says:

[...] screen cast. The next step I wanted to play with was validation. Hamilton Verissimo has a nice screen cast showing off the new functionality with javascript agnostic code. Very cool that MR insulates you [...]

shahzad Says:

I have finaly started playing with Monorail. I am impressed, though I am not an expert… To answer Rhywun’s question above, $Form.FormTag(”%{action=’Create’, immediate=’true’, useTitles=’true’}”) didn’t seem to work for me either. So, I took out the useTitles=’true’ part and everything was fine.

Zen and the art of Castle maintenance » Blog Archive » jQuery and MonoRail Says:

[...] form validation [...]

ranga Says:

my entity like this

public string SiteName { get; set; }

public string SupprotContactEmailAddress { get; set; }

public int PasswordExpiryInterval { get; set; }

[ValidateInteger("integer msg"), ValidateNonEmpty("requird msg")]
public int NumberOfPasswordRetries { get; set; }

but whn i try to submit my page without entering anything to NumberOfPasswordRetries fld..it shows me both erroe messages (integer validation and required fld validation) but this time i need only validation for requird fld..so can u give me a help

Leave a Reply