Skip to content
jwsher edited this page Nov 3, 2011 · 9 revisions

Welcome to the ValidatableForm wiki!

What is ValidatableForm?

ValidatableForm is an extensible type safe Scala library that you can use to validate web forms. It can be used as a general framework for validating just about any web form imaginable.

Can you show me some basic usage examples?

The automated test script ValidationTest.scala has a lot of examples.

Here's a simple form with just a required zipcode.

      val f = new ValidatableForm((e) => {}, "zipcode" -> new ValidString(List(new ValidRegex("^([0-9]{5})$"), new Required)))
      f.submit(Map("zipcode" -> "a12345"))
      assert(!f("zipcode").isValid)
      f.submit(Map("zipcode" -> "01234"))
      assert(f("zipcode").isValid)

** How do I use it with Lift? **

In a Snippet

      
      import com.scalabb.validation._
      class Login {

      def handleErr( err : List[FormError]) =  {
        for ( e <- err) {
          e.v match {
          case Some(v) => S.error(S.?(v.name+"."+e.i18nCode,e.msgArgs : _* ))
          case _ => S.error(S.?("form."+e.i18nCode,e.msgArgs : _* ))
          }
        }
      }

     val minSignup : ValidatableForm = new ValidatableForm(handleErr
        ,"username" ->
            new ValidUsername(List(new Required))
       ,"password" ->
            new ValidPassword(List(new Required)))


     def login(in :NodeSeq) : NodeSeq = { 
      bind("login",in,
       "username" ->
        SHtml.text(minSignup("username").toString,minSignup("username").submit),
       "password" ->
        SHtml.password(minSignup("password").toString,minSignup("password").submit),
       "submit" -> 
        SHtml.submit("Submit",() => { 
          if (minSignup.isValid) {
            val auth= None //Lookup user name and password
             auth match  {
              case Some(a) => {
                  //Save login info
            	  redirectTo("/loginOk")
              }
              case _ => { 
            	  S.error("Username or Password is invalid");
              }
         }            				 
      } 
    } 
  }
    <lift:Login.login form="POST">
        <table>
        <tr>
            <td style="vertical-align:top;">
                <label for="username">
                    Username:
                </label>
            </td>
            <td>
                <login:username/>
            </td>
        </tr>
        <tr>
            <td style="vertical-align:top;">
                <label for="password">
                    Password:
                </label>
            </td>
            <td>
                <login:password/>
                <br/>
                <login:submit/>
            </td>
        </tr>
       </table>

How Do I Extend It?

There are three ways you can Extend ValidatableForm.

New Validators:

class UniqueUsername extends Validator[String] {
	def validate(obj: String) :Boolean = { 
			BbUser.findByUsername(obj) match { 
				case None => true
				case _ => false
			}
	}
	def error() : String = {
		"That username is already in use by another user"
	}
	def i18nError() : String = {
		"username.exists"
	}	
        def msgArgs() : List[String] = List();
}

  val minSignup : ValidatableForm = new ValidatableForm(handleErr,
    "username" ->
            new ValidUsername(List(new Required,new UniqueUsername)))

You can also make new Validatable Types

class ValidCaptcha(validators: List[Validator[String]]) extends ValidString(validators) {
  override def classValidators: List[Validator[String]] = {
      return List(new CaptchaValidator());
  }
  def renderCaptcha() : NodeSeq = {
        <img src={ "/"+ValidCaptcha.path.mkString("/") } />
  }
  
}

class CaptchaValidator extends Validator[String] {
  def validate(obj: String) :Boolean = {
    ValidCaptcha.validateCaptcha(obj);
  }
  def error() : String = {
    "The captcha is invalid"
  }
  def i18nError() : String = {
    "captcha.invalid"
  }
  def msgArgs() : List[String] = List();
}

You can also make new form level Validators

class FieldsMatch(fields: List[String]) extends Validator[ValidatableForm] {
	def validate(obj: ValidatableForm) :Boolean = {
		var field :Option[ValidField[ _ <: Any]] = None
		for( f <- fields) { 
			field match   { 
				case None => 
					field = Some(obj(f))
				case Some(x) => { 
					val  field: Any=obj(f).toModel; 
					val  prev: Any=x.toModel;
					if (!prev.equals(field)) return false
				}
			}
		}
		return true
	}
	def error() : String = {
		"Values must match"
	}

	def i18nError() : String = {
		"value.must-match"
	}	
        def msgArgs() : List[String] = List();

}

How do I get my data out once the form is valid?

   val minSignup : ValidatableForm = new ValidatableForm(handleErr
        ,"username" ->
            new ValidUsername(List(new Required))
       ,"password" ->
            new ValidPassword(List(new Required)))

...

 if (minSignup.isValid) { 
       System.out.println("Username is "+minSignup("username").toString()+" password is "+minSignup("password"));
}

How Do I use it with Maven?

 <repositories>
   <repository>
        <id>jwsher-snapshots</id>
        <url>http://github.com/jwsher/jwsher-mvn-repo/raw/master/releases</url>
    </repository>
</repositories>

 <dependencies>
    <dependency>
      <groupId>com.scalabb</groupId>
      <artifactId>validatable-form</artifactId>
      <version>0.8.1</version>
    </dependency>
</dependencies>

Clone this wiki locally