Form module
We can delete an album, so why don't we proceed to add album functionality now? It will require a bit more effort, because we actually need some kind of a form with fields to create a new album. Fortunately, there's a helper module in Suave library exactly for this purpose.
Note:
Suave.Form
module at the time of writing is still inExperimental
package - just asSuave.Html
which we're already using.
First, let's create a separate module Form
to keep all of our forms in there (yes there will be more soon).
Add the Form.fs
file just before View.fs
- both View
and App
module will depend on Form
.
As with the rest of modules, don't forget to follow our modules naming convention.
Now declare the first Album
form:
Form.fs
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: |
|
Album
type contains all fields needed for the form.
For the moment, Suave.Form
supports following types of fields:
- decimal
- string
- System.Net.Mail.MailAddress
- Suave.Form.Password
Note: the int type is not supported yet, however we can easily convert from decimal to int and vice versa
Afterwards comes a declaration of the album form itself. It consists of list of "Props" (Properties), of which we can think as of validations:
- First, we declared that the
Title
must be of max length 100 - Second, we declared the same for
ArtUrl
- Third, we declared that the
Price
must be between 0.01 and 100.0 with a step of 0.01 (this means that for example 1.001 is invalid)
Those properties can be now used as both client and server side.
For client side we will use the album
declaration in our View
module in order to output HTML5 input validation attributes.
For server side we will use an utility WebPart that will parse the form field values from a request.
Note: the above snippet uses F# Quotations - a feature that you can read more about here. For the sake of tutorial, you only need to know that they allow Suave to lookup the name of a Field from a property getter.
To see how we can use the form in View
module, add open Suave.Form
to the beginning:
View.fs
1: 2: 3: 4: |
|
Next, add this block of code:
View.fs
20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: |
|
Above snippet is quite long but, as we'll soon see, we'll be able to reuse it a few times.
The FormLayout
types defines a layout for a form and consists of:
SubmitText
that will be used for the string value of submit buttonFieldsets
- a list ofFieldset
valuesForm
- instance of the form to render
The Fieldset
type defines a layout for a fieldset:
Legend
is a string value for a set of fieldsFields
is a list ofField
values
The Field
type has:
- a
Label
string Html
- function which takesForm
and returnsNode
(object model for HTML markup). It might seem cumbersome, but the signature is deliberate in order to make use of partial application
Note: all of above types are generic, meaning they can accept any type of form, but the form's type must be consistent with the
FormLayout
hierarchy.
renderForm
is a reusable function that takes an instance of FormLayout
and returns HTML object model:
- it creates a form element
- the form contains a list of fieldsets, each of which:
- outputs its legend first
- iterates over its
Fields
and- outputs div element with label element for the field
- outputs div element with target input element for the field
- the form ends with a submit buttonMultiple items
namespace FSharp
--------------------
namespace Microsoft.FSharpMultiple items
namespace FSharp.Data
--------------------
namespace Microsoft.FSharp.Datanamespace FSharp.Data.SqlMultiple items
type LiteralAttribute =
inherit Attribute
new : unit -> LiteralAttribute
Full name: Microsoft.FSharp.Core.LiteralAttribute
--------------------
new : unit -> LiteralAttributeval ConnectionString : string
Full name: SuaveMusicStore.Db.ConnectionStringtype Sql = SqlDataProvider<...>
Full name: SuaveMusicStore.Db.Sqltype SqlDataProvider
Full name: FSharp.Data.Sql.SqlDataProvider
<summary>Typed representation of a database</summary>
<param name='ConnectionString'>The connection string for the SQL database</param>
<param name='ConnectionStringName'>The connection string name to select from a configuration file</param>
<param name='DatabaseVendor'> The target database vendor</param>
<param name='IndividualsAmount'>The amount of sample entities to project into the type system for each SQL entity type. Default 1000.</param>
<param name='UseOptionTypes'>If true, F# option types will be used in place of nullable database columns. If false, you will always receive the default value of the column's type even if it is null in the database.</param>
<param name='ResolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types.</param>
<param name='Owner'>The owner of the schema for this provider to resolve (Oracle Only)</param>
<param name='CaseSensitivityChange'>Should we do ToUpper or ToLower when generating table names?</param>
<param name='TableNames'>Comma separated table names list to limit a number of tables in big instances. The names can have '%' sign to handle it as in the 'LIKE' query (Oracle and MSSQL Only)</param>
<param name='OdbcQuote'>Odbc quote characters: Quote characters for the table and column names: `alias`, [alias]</param>
<param name='SQLiteLibrary'>Use System.Data.SQLite or Mono.Data.SQLite or select automatically (SQLite only)</param>
namespace FSharp.Data.Sql.Commontype DatabaseProviderTypes =
| MSSQLSERVER = 0
| SQLITE = 1
| POSTGRESQL = 2
| MYSQL = 3
| ORACLE = 4
| MSACCESS = 5
| ODBC = 6
| FIREBIRD = 7
Full name: FSharp.Data.Sql.Common.DatabaseProviderTypesCommon.DatabaseProviderTypes.POSTGRESQL: Common.DatabaseProviderTypes = 2type CaseSensitivityChange =
| ORIGINAL = 0
| TOUPPER = 1
| TOLOWER = 2
Full name: FSharp.Data.Sql.Common.CaseSensitivityChangeCommon.CaseSensitivityChange.ORIGINAL: Common.CaseSensitivityChange = 0type DbContext = SqlDataProvider<...>.dataContext
Full name: SuaveMusicStore.Db.DbContexttype dataContext =
member ClearUpdates : unit -> List<SqlEntity>
member CreateConnection : unit -> IDbConnection
member GetUpdates : unit -> List<SqlEntity>
member Public : publicSchema
member SubmitUpdates : unit -> Unit
member SubmitUpdatesAsync : unit -> Async<Unit>
nested type public.albumdetails.Individuals
nested type public.albumdetailsEntity
nested type public.albums.Individuals
nested type public.albumsEntity
...
Full name: FSharp.Data.Sql.SqlDataProvider,DatabaseVendor="2",ConnectionString="Server=192.168.99.100;Database=suavemusicstore;User Id=suave;Password=1234;",CaseSensitivityChange="0".dataContexttype Album = SqlDataProvider<...>.dataContext.public.albumsEntity
Full name: SuaveMusicStore.Db.Albumtype Genre = SqlDataProvider<...>.dataContext.public.genresEntity
Full name: SuaveMusicStore.Db.Genretype AlbumDetails = SqlDataProvider<...>.dataContext.public.albumdetailsEntity
Full name: SuaveMusicStore.Db.AlbumDetailsval getContext : unit -> SqlDataProvider<...>.dataContext
Full name: SuaveMusicStore.Db.getContextSqlDataProvider<...>.GetDataContext() : SqlDataProvider<...>.dataContext
<summary>Returns an instance of the SQL Provider using the static parameters</summary>
SqlDataProvider<...>.GetDataContext(transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext
<summary>Returns an instance of the SQL Provider</summary>
<param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>
SqlDataProvider<...>.GetDataContext(connectionString: string) : SqlDataProvider<...>.dataContext
<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
SqlDataProvider<...>.GetDataContext(connectionString: string, transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext
<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
<param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>
SqlDataProvider<...>.GetDataContext(connectionString: string, resolutionPath: string) : SqlDataProvider<...>.dataContext
<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
<param name='resolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types</param>
SqlDataProvider<...>.GetDataContext(connectionString: string, resolutionPath: string, transactionOptions: Transactions.TransactionOptions) : SqlDataProvider<...>.dataContext
<summary>Returns an instance of the SQL Provider</summary>
<param name='connectionString'>The database connection string</param>
<param name='resolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types</param>
<param name='transactionOptions'>TransactionOptions for the transaction created on SubmitChanges.</param>val getGenres : ctx:DbContext -> Genre list
Full name: SuaveMusicStore.Db.getGenresval ctx : DbContexttype 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>property SqlDataProvider<...>.dataContext.Public: SqlDataProvider<...>.dataContext.publicSchemaproperty SqlDataProvider<...>.dataContext.publicSchema.Genres: SqlDataProvider<...>.dataContext.publicSchema.public.genres
<summary> The base table genres belonging to schema public</summary>Multiple items
module Seq
from FSharp.Data.Sql
--------------------
module Seq
from Microsoft.FSharp.Collectionsval toList : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.Seq.toListval getAlbumsForGenre : genreName:string -> ctx:DbContext -> Album list
Full name: SuaveMusicStore.Db.getAlbumsForGenreval genreName : stringval query : Linq.QueryBuilder
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.queryval album : SqlDataProvider<...>.dataContext.public.albumsEntityproperty SqlDataProvider<...>.dataContext.publicSchema.Albums: SqlDataProvider<...>.dataContext.publicSchema.public.albums
<summary> The base table albums belonging to schema public</summary>custom operation: join var in collection on (outerKey = innerKey). Note that parentheses are required after 'on'
Calls Linq.QueryBuilder.Joinval genre : SqlDataProvider<...>.dataContext.public.genresEntityproperty SqlDataProvider<...>.dataContext.public.genresEntity.Genreid: int
<summary> integer</summary>custom operation: where (bool)
Calls Linq.QueryBuilder.Whereproperty SqlDataProvider<...>.dataContext.public.genresEntity.Name: string
<summary> character varying(120)</summary>custom operation: select ('Result)
Calls Linq.QueryBuilder.Selectval getAlbumDetails : id:int -> ctx:DbContext -> AlbumDetails option
Full name: SuaveMusicStore.Db.getAlbumDetailsval id : inttype 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>val album : SqlDataProvider<...>.dataContext.public.albumdetailsEntityproperty SqlDataProvider<...>.dataContext.publicSchema.Albumdetails: SqlDataProvider<...>.dataContext.publicSchema.public.albumdetails
<summary> The view albumdetails belonging to schema public</summary>property SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumid: int
<summary> integer</summary>val tryHead : source:seq<'T> -> 'T option
Full name: Microsoft.FSharp.Collections.Seq.tryHeadval getAlbumsDetails : ctx:DbContext -> AlbumDetails list
Full name: SuaveMusicStore.Db.getAlbumsDetailsMultiple items
module List
from FSharp.Data.Sql
--------------------
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>val sortBy : projection:('T -> 'Key) -> list:'T list -> 'T list (requires comparison)
Full name: Microsoft.FSharp.Collections.List.sortByval a : SqlDataProvider<...>.dataContext.public.albumdetailsEntityproperty SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Artist: string
<summary> character varying(120)</summary>val getAlbum : id:int -> ctx:DbContext -> Album option
Full name: SuaveMusicStore.Db.getAlbumproperty SqlDataProvider<...>.dataContext.public.albumsEntity.Albumid: int
<summary> integer</summary>val deleteAlbum : album:Album -> ctx:DbContext -> Unit
Full name: SuaveMusicStore.Db.deleteAlbumval album : Albummember Common.SqlEntity.Delete : unit -> unitSqlDataProvider<...>.dataContext.SubmitUpdates() : Unit
<summary>Save changes to data-source. May throws errors: To deal with non-saved items use GetUpdates() and ClearUpdates().</summary>type IntPath = PrintfFormat<(int -> string),unit,string,string,int>
Full name: SuaveMusicStore.Path.IntPathMultiple items
type PrintfFormat<'Printer,'State,'Residue,'Result> =
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>
member Value : string
Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_>
--------------------
type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> =
inherit PrintfFormat<'Printer,'State,'Residue,'Result>
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>
Full name: Microsoft.FSharp.Core.PrintfFormat<_,_,_,_,_>
--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result>
--------------------
new : value:string -> PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.stringtype unit = Unit
Full name: Microsoft.FSharp.Core.unitval withParam : key:string * value:string -> path:string -> string
Full name: SuaveMusicStore.Path.withParamval key : stringval value : stringval path : stringval sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintfval home : string
Full name: SuaveMusicStore.Path.homeval overview : string
Full name: SuaveMusicStore.Path.Store.overviewval browse : string
Full name: SuaveMusicStore.Path.Store.browseval details : IntPath
Full name: SuaveMusicStore.Path.Store.detailsval browseKey : string
Full name: SuaveMusicStore.Path.Store.browseKeymodule Admin
from SuaveMusicStore.Pathval manage : string
Full name: SuaveMusicStore.Path.Admin.manageval deleteAlbum : IntPath
Full name: SuaveMusicStore.Path.Admin.deleteAlbumnamespace Suavemodule Form
from Suavetype Album =
{ArtistId: decimal;
GenreId: decimal;
Title: string;
Price: decimal;
ArtUrl: string;}
Full name: SuaveMusicStore.Form.AlbumAlbum.ArtistId: decimalMultiple items
val decimal : value:'T -> decimal (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.decimal
--------------------
type decimal = System.Decimal
Full name: Microsoft.FSharp.Core.decimal
--------------------
type decimal<'Measure> = decimal
Full name: Microsoft.FSharp.Core.decimal<_>Album.GenreId: decimalAlbum.Title: stringAlbum.Price: decimalAlbum.ArtUrl: stringval album : Form<Album>
Full name: SuaveMusicStore.Form.albumMultiple items
union case Form.Form: FormProp<'a> list * ServerSideValidation<'a> list -> Form<'a>
--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list
Full name: Suave.Form.Form<_>union case FormProp.TextProp: Property<'a,string> -> FormProp<'a>val f : Albumval maxLength : max:int -> Validation<string>
Full name: Suave.Form.maxLengthunion case FormProp.DecimalProp: Property<'a,decimal> -> FormProp<'a>val min : min:decimal -> Validation<decimal>
Full name: Suave.Form.minval max : max:decimal -> Validation<decimal>
Full name: Suave.Form.maxval step : step:System.Decimal -> Validation<decimal>
Full name: Suave.Form.stepmodule Html
from Suaveval em : s:string -> Node
Full name: SuaveMusicStore.View.emval s : stringval tag : tag:string -> attr:Attribute list -> contents:Node list -> Node
Full name: Suave.Html.tagunion case Node.Text: string -> Nodeval cssLink : href:string -> Node
Full name: SuaveMusicStore.View.cssLinkval href : stringval link : attr:Attribute list -> Node
Full name: Suave.Html.linkval h2 : s:string -> Node
Full name: SuaveMusicStore.View.h2val ul : nodes:Node list -> Node
Full name: SuaveMusicStore.View.ulval nodes : Node listval li : (Node list -> Node)
Full name: SuaveMusicStore.View.lival table : x:Node list -> Node
Full name: SuaveMusicStore.View.tableval x : Node listval th : x:Node list -> Node
Full name: SuaveMusicStore.View.thval tr : x:Node list -> Node
Full name: SuaveMusicStore.View.trval td : x:Node list -> Node
Full name: SuaveMusicStore.View.tdval strong : s:string -> Node
Full name: SuaveMusicStore.View.strongval text : s:string -> Node list
Full name: Suave.Html.textval form : x:Node list -> Node
Full name: SuaveMusicStore.View.formval submitInput : value:string -> Node
Full name: SuaveMusicStore.View.submitInputval input : attr:Attribute list -> Node
Full name: Suave.Html.inputtype Field<'a> =
{Label: string;
Html: Form<'a> -> Node;}
Full name: SuaveMusicStore.View.Field<_>Field.Label: stringMultiple items
Field.Html: Form<'a> -> Node
--------------------
type HtmlAttribute = string * string
Full name: Suave.Form.HtmlAttributeMultiple items
union case Form.Form: FormProp<'a> list * ServerSideValidation<'a> list -> Form<'a>
--------------------
module Form
from SuaveMusicStore
--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list
Full name: Suave.Form.Form<_>type Node =
| Element of Element * Node list
| VoidElement of Element
| Text of string
| Raw of string
| WhiteSpace of string
Full name: Suave.Html.Nodetype Fieldset<'a> =
{Legend: string;
Fields: Field<'a> list;}
Full name: SuaveMusicStore.View.Fieldset<_>Fieldset.Legend: stringFieldset.Fields: Field<'a> listtype FormLayout<'a> =
{Fieldsets: Fieldset<'a> list;
SubmitText: string;
Form: Form<'a>;}
Full name: SuaveMusicStore.View.FormLayout<_>FormLayout.Fieldsets: Fieldset<'a> listFormLayout.SubmitText: stringMultiple items
FormLayout.Form: Form<'a>
--------------------
module Form
from SuaveMusicStore
--------------------
type Form<'a> = | Form of FormProp<'a> list * ServerSideValidation<'a> list
Full name: Suave.Form.Form<_>val renderForm : layout:FormLayout<'a> -> Node
Full name: SuaveMusicStore.View.renderFormval layout : FormLayout<'a>val set : Fieldset<'a>val field : Field<'a>val div : (Attribute list -> Node list -> Node)
Full name: Suave.Html.divField.Html: Form<'a> -> NodeFormLayout.Form: Form<'a>val home : Node list
Full name: SuaveMusicStore.View.homeval store : genres:string list -> Node list
Full name: SuaveMusicStore.View.storeval genres : string listval p : (Attribute list -> Node list -> Node)
Full name: Suave.Html.pMultiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>val length : list:'T list -> int
Full name: Microsoft.FSharp.Collections.List.lengthval genre : stringval url : stringmodule Path
from SuaveMusicStoremodule Store
from SuaveMusicStore.Pathval a : href:string -> attr:Attribute list -> (Node list -> Node)
Full name: Suave.Html.aval browse : genre:string -> albums:Db.Album list -> Node list
Full name: SuaveMusicStore.View.browseval albums : Db.Album listmodule Db
from SuaveMusicStoretype Album = FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity
Full name: SuaveMusicStore.Db.Albumval album : Db.Albumval details : Path.IntPath
Full name: SuaveMusicStore.Path.Store.detailsproperty FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Albumid: int
<summary> integer</summary>property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumsEntity.Title: string
<summary> character varying(160)</summary>val details : album:Db.AlbumDetails -> Node list
Full name: SuaveMusicStore.View.detailsval album : Db.AlbumDetailstype AlbumDetails = FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity
Full name: SuaveMusicStore.Db.AlbumDetailsproperty FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Title: string
<summary> character varying(160)</summary>val img : attr:Attribute list -> Node
Full name: Suave.Html.imgproperty FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumarturl: string
<summary> character varying(1024)</summary>val caption : stringval t : stringproperty FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Genre: string
<summary> character varying(120)</summary>property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Artist: string
<summary> character varying(120)</summary>property FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Price: decimal
<summary> numeric</summary>System.Decimal.ToString() : string
System.Decimal.ToString(provider: System.IFormatProvider) : string
System.Decimal.ToString(format: string) : string
System.Decimal.ToString(format: string, provider: System.IFormatProvider) : stringval truncate : k:int -> s:string -> string
Full name: SuaveMusicStore.View.truncateval k : intproperty System.String.Length: intSystem.String.Substring(startIndex: int) : string
System.String.Substring(startIndex: int, length: int) : stringval manage : albums:Db.AlbumDetails list -> Node list
Full name: SuaveMusicStore.View.manageval albums : Db.AlbumDetails listval deleteAlbum : Path.IntPath
Full name: SuaveMusicStore.Path.Admin.deleteAlbumproperty FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.albumdetailsEntity.Albumid: int
<summary> integer</summary>val deleteAlbum : albumTitle:string -> Node list
Full name: SuaveMusicStore.View.deleteAlbumval albumTitle : stringval br : attr:Attribute list -> Node
Full name: Suave.Html.brval notFound : Node list
Full name: SuaveMusicStore.View.notFoundval index : container:Node list -> string
Full name: SuaveMusicStore.View.indexval container : Node listval html : (Attribute list -> Node list -> Node)
Full name: Suave.Html.htmlval head : (Attribute list -> Node list -> Node)
Full name: Suave.Html.headval title : attr:Attribute list -> s:string -> Node
Full name: Suave.Html.titleval body : (Attribute list -> Node list -> Node)
Full name: Suave.Html.bodyval htmlToString : node:Node -> string
Full name: Suave.Html.htmlToStringmodule App
from SuaveMusicStoremodule Filters
from Suavemodule Operators
from Suavemodule RequestErrors
from Suavemodule Successful
from Suavemodule Web
from Suaveval html : container:Html.Node list -> WebPart
Full name: SuaveMusicStore.App.htmlval container : Html.Node listval OK : body:string -> WebPart
Full name: Suave.Successful.OKmodule View
from SuaveMusicStoreval index : container:Html.Node list -> string
Full name: SuaveMusicStore.View.indexval browse : (HttpContext -> Async<HttpContext option>)
Full name: SuaveMusicStore.App.browseval request : apply:(HttpRequest -> HttpContext -> 'a) -> context:HttpContext -> 'a
Full name: Suave.Http.requestval r : HttpRequestmember HttpRequest.queryParam : key:string -> Choice<string,string>union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>val getContext : unit -> FSharp.Data.Sql.SqlDataProvider<...>.dataContext
Full name: SuaveMusicStore.Db.getContextval getAlbumsForGenre : genreName:string -> ctx:Db.DbContext -> Db.Album list
Full name: SuaveMusicStore.Db.getAlbumsForGenreval browse : genre:string -> albums:Db.Album list -> Html.Node list
Full name: SuaveMusicStore.View.browseunion case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>val msg : stringval BAD_REQUEST : body:string -> WebPart
Full name: Suave.RequestErrors.BAD_REQUESTval overview : (HttpContext -> Async<HttpContext option>)
Full name: SuaveMusicStore.App.overviewval warbler : f:('t -> 't -> 'u) -> 't -> 'u
Full name: Suave.WebPart.warblerval getGenres : ctx:Db.DbContext -> Db.Genre list
Full name: SuaveMusicStore.Db.getGenresval map : mapping:('T -> 'U) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.mapval g : Db.Genreproperty FSharp.Data.Sql.SqlDataProvider<...>.dataContext.public.genresEntity.Name: string
<summary> character varying(120)</summary>val store : genres:string list -> Html.Node list
Full name: SuaveMusicStore.View.storeval details : id:int -> WebPart
Full name: SuaveMusicStore.App.detailsval getAlbumDetails : id:int -> ctx:Db.DbContext -> Db.AlbumDetails option
Full name: SuaveMusicStore.Db.getAlbumDetailsunion case Option.Some: Value: 'T -> Option<'T>val details : album:Db.AlbumDetails -> Html.Node list
Full name: SuaveMusicStore.View.detailsunion case Option.None: Option<'T>val never : WebPart<'a>
Full name: Suave.WebPart.neverval manage : (HttpContext -> Async<HttpContext option>)
Full name: SuaveMusicStore.App.manageval getAlbumsDetails : ctx:Db.DbContext -> Db.AlbumDetails list
Full name: SuaveMusicStore.Db.getAlbumsDetailsval manage : albums:Db.AlbumDetails list -> Html.Node list
Full name: SuaveMusicStore.View.manageval deleteAlbum : id:int -> WebPart<HttpContext>
Full name: SuaveMusicStore.App.deleteAlbumval ctx : FSharp.Data.Sql.SqlDataProvider<...>.dataContextval getAlbum : id:int -> ctx:Db.DbContext -> Db.Album option
Full name: SuaveMusicStore.Db.getAlbumval choose : options:WebPart<'a> list -> WebPart<'a>
Full name: Suave.WebPart.chooseval GET : WebPart
Full name: Suave.Filters.GETval deleteAlbum : albumTitle:string -> Html.Node list
Full name: SuaveMusicStore.View.deleteAlbumval POST : WebPart
Full name: Suave.Filters.POSTval deleteAlbum : album:Db.Album -> ctx:Db.DbContext -> Unit
Full name: SuaveMusicStore.Db.deleteAlbummodule Redirection
from Suaveval FOUND : location:string -> WebPart
Full name: Suave.Redirection.FOUNDval webPart : WebPart<HttpContext>
Full name: SuaveMusicStore.App.webPartval path : pathAfterDomain:string -> WebPart
Full name: Suave.Filters.pathval home : Html.Node list
Full name: SuaveMusicStore.View.homeval pathScan : pf:PrintfFormat<'a,'b,'c,'d,'t> -> h:('t -> WebPart) -> WebPart
Full name: Suave.Filters.pathScanval pathRegex : pathAfterDomainRegex:string -> WebPart
Full name: Suave.Filters.pathRegexmodule Files
from Suaveval browseHome : WebPart
Full name: Suave.Files.browseHomeval notFound : Html.Node list
Full name: SuaveMusicStore.View.notFoundval startWebServer : config:SuaveConfig -> webpart:WebPart -> unit
Full name: Suave.Web.startWebServerval defaultConfig : SuaveConfig
Full name: Suave.Web.defaultConfig
Show code from this section on GitHub