Giter Site home page Giter Site logo

zaaack / fable-validation Goto Github PK

View Code? Open in Web Editor NEW
49.0 5.0 0.0 289 KB

An isomorphic validation library for Fable/F#, inspired by elm-validate

License: MIT License

Batchfile 0.43% F# 97.42% Shell 1.24% JavaScript 0.91%
fable validation elmish

fable-validation's Introduction

Fable.Validation

Build Status NuGet version

Install

paket add Fable.Validation

OR

dotnet add package Fable.Validation

Usage

Example

all is a validate function, it has a parameter to pass a callback with the only argument of a validator instance, you can write your validate rules and return the Ok value. all means validate all fields, if you want to return early after first error, you can use fast, there are also allAsync, fastAsync for async validate support.

open System
open Fable.Core
open Fable.Core.JsInterop
open Fable.Core.Testing
open Fable.Validation.Core

type People = {
    name: string
    age: int
}  with
    static member Name = "name"
    static member Age = "age"

let valid = { name="abcd"; age=10 }
let result = all <| fun t ->

    { name = t.Test People.Name valid.name // call `t.Test fieldName value` to initialize field state
                |> t.Trim // pipe the field state to rules
                |> t.NotBlank "name cannot be blank" // rules can contain params and a generic error message
                |> t.MaxLen 20 "maxlen is {len}"
                |> t.MinLen 4 "minlen is {len}"
                |> t.End // call `t.End` to unwrap the validated
                         // and transformed value,
                         // you can use the transformed values to create a new model

      age = t.Test People.Age valid.age
                |> t.Gt 0 "should greater then {min}"
                |> t.Lt 200 "shoudld less then {max}"
                |> t.End }

Assert.AreEqual (result, Ok(valid))

// the result type is Result<'T, 'E list>
let result: Result<People, string list> = all <| fun t ->

    { name = t.Test People.Name "abc"
                |> t.MaxLen 20 "maxlen is 20"
                |> t.MinLen 4 "minlen is 4"
                |> t.End
      age = t.Test People.Age 201
                |> t.Gt 0 "should greater then 0"
                |> t.Lt 200 "should less then 200"
                |> t.End }

Assert.AreEqual (result, Error(Map [ People.Name, ["minlen is 4"]
                                     People.Age, ["should less then 200"] ]))

// async validate example

async {
    let valid = { name=" abcd "; age=10 }

    let testNameAsync =
        IsValidOptAsync<string, string, string> <| fun name ->
            async { return Valid (name.Trim()) }

    // fast validation
    let! result = fastAsync <| fun t ->
        async {
            let! name = t.Test People.Name valid.name
                        |> t.ToAsync
                        |> testNameAsync "should be right"
                        |> t.EndAsync

            return { name = name
                     age = t.Test People.Age valid.age
                            |> t.Gt 0 "shoud greater then 0"
                            |> t.Lt 200 "should less then 200"
                            |> t.End }
        }

    Assert.AreEqual (result, Ok({name="abcd"; age=10}))
} |> Async.StartImmediately

// validate single value

// result is Ok(transformed input value) or Error(error list)
// test single value don't need call `t.End`, because it will return as result.
let result: Result<string, string list> = single <| fun t ->
    t.TestOne "Some Input" |> t.MinLen 10 "minlen is 10" |> t.End

Option/Result support

This library comes with Option/Result support in mind, you can unwrap it by validate rules like IsSome/IsOK, or skip following validation it if it's None/Error.

let result: Result<string, string list> = single <| fun t ->
    t.TestOne (Some 1) |> t.IsSome  "should be some" |> t.Gt 0 "should greater then 0" |> t.End

// In this case you don't need to call t.End and rules are a list of rule,
// it will return None if it's None and don't cause any error.
// there are TestOneOnlySome/TestOneOnlyOk/TestOneOnlySomeAsync/TestOneOnlyOkAsync for single field test
// and TestOnlySome/TestOnlyOk/TestOnlySomeAsync/TestOnlyOkAsync for multi fields test
let result: Result<string, string list> = single <| fun t ->
    t.TestOneOnlySome None [ t.Gt 0 "should greater then 0" ]

Map/To

It's very easy to transform the input value to another type:

  • t.Map Lift the input value's type, it shouldn't throw error
  • t.To Parse the input value to another type, it could throw error.
let result: Result<int option, string list> =
    single (fun t -> t.TestOne 1 |> t.Map Some |> t.End)

let result: Result<int, string list> =
    single (fun t -> t.TestOne "123" |> t.To int "cann't parse to int" |> t.End)

For more you can see API Reference.

License

MIT

fable-validation's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

fable-validation's Issues

Example in MVU

Hi Zaaack,

This looks like a really helpful library. I'm just trying to do validation with elmish for the first time and I'm struggling to find an example of how to use the validation in the UI.

It's very clear how to construct the rules but I can't see if I should validate as a service with messages or in the view?

Even a link to another resource, perhaps some source code you used fable.validation.core in would be very helpful.

Type not as expected

Hi sorry to bother you again, perhaps this library isn't getting a lot of attention, I don't think its been changed in a few years.

// the result type is Result<'T, 'E list>
let result: Result<People, string list> = all <| fun t ->

    { name = t.Test People.Name "abc"
                |> t.MaxLen 20 "maxlen is 20"
                |> t.MinLen 4 "minlen is 4"
                |> t.End
      age = t.Test People.Age 201
                |> t.Gt 0 "should greater then 0"
                |> t.Lt 200 "should less then 200"
                |> t.End }

Assert.AreEqual (result, Error(Map [ People.Name, ["minlen is 4"]
                                     People.Age, ["should less then 200"] ]))

Docs suggest should expect a List of errors but all returns a Map of errors for example
a Map<string, string list>

From my observations I'm getting just a single error in my string list back. This is the behavior I might expect from fast but I'm getting on all.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.