mangelmaxime / fable.form Goto Github PK
View Code? Open in Web Editor NEWHome Page: https://mangelmaxime.github.io/Fable.Form/
License: Other
Home Page: https://mangelmaxime.github.io/Fable.Form/
License: Other
There should be a way to add detailed help/description to individual form fields
At the moment there is no way to explicitly abandon the form - i.e. I can't see how a "Cancel" button can be added. This is a standard usability feature. At the moment I'm stuck on the form page, and either have to put a button somewhere before/after it, or navigate away by the means of "back" navigation or using navbar, if there is one.
I'm sure I can add the necessary code myself - would you accept the PR if it's working?
In general, we don't use that specificities of Fable.Form executing the form requires the FormValues and that's not what we send to the server in general.
Indeed, in general we send the FormValue which is the parsers output.
It would be nice to have the ability to render the form as readonly.
Such as if we have a property:
RenderMode = Review | Edit
...where if form is in "ReadOnly" mode, it would display "labels" instead of the regular "input" fields? (which would essentially be the same input fields with the "readonly" modifier, and a class to take away the border from the input field).
The purpose would be to be able to review the same data in the same layout that it was input but non-editable.
The form would be able to switch form edit <-> review on demand.
In a same way that a field can be disabled, I think adding IsLoading
to the field config can make sense.
I am unsure if we should do it the field config level or if it should be at the Attributes
level (per case by case).
I think slight in favour of doing it as the config level and if a type of field doesn't suppose loading then it can just ignore that property.
Doing it at the config level, imply that Fable.Form will have a Base.setLoading
function in it like Base.disable
.
should have no references to code outside App.fs and not contain anything extraneous.
First off, the "Form.reactComponentField" is great! That said, it would be awesome to be able to expand the type of fields that Fable Forms can support through the use of plugins/extensions that we can all build/publish. Again, the reactComponentField works great, but a rigid contract will guarantee consistency.
We'll be trying to build a couple of them using reactComponentField for now:
I am busy setting up a simple, but long form..
The code compiles perfectly fine, but when I want to render the form i get:
Uncaught Error: Currying to more than 8-arity is not supported: 11
at curry (Util.js?2ca6:569)
at form (ReceivingForm.fs.js?39f6:115)
at eval (ReceivingPage.fs.js?c5b2:55)
at Enumerator_Seq.eval [as f] (Seq.js?8dfc:338)
at Enumerator_Seq.GetEnumerator (Seq.js?8dfc:64)
at getEnumerator (Util.js?2ca6:50)
at Enumerator_FromFunctions$1.eval [as next] (Seq.js?8dfc:198)
at Enumerator_FromFunctions$1.System.Collections.IEnumerator.MoveNext (Seq.js?8dfc:99)
at Enumerator_FromFunctions$1.eval [as next] (Seq.js?8dfc:181)
at Enumerator_FromFunctions$1.System.Collections.IEnumerator.MoveNext (Seq.js?8dfc:99)
Is it a restriction in the library? Does it only allow 8 fields in a form max due to the util?
There doesn't appear to be a start script so 'npm start' doesn't run. Can you add some simple instructions to run the examples please.
These are very common types of input and should be easy to add. Best to have all three:
// Example of implementation
// To be splitted in the different package
module Form =
module Base =
open Fable.Form.Base
let disable (form : Form<'Values, 'Output, 'Field>) : Form<'Values, 'Output, 'Field> =
Form (
fun values ->
let filled =
fill form values
{
Fields =
filled.Fields
|> List.map (fun filledField ->
{ filledField with IsDisabled = true}
)
Result = filled.Result
IsEmpty = filled.IsEmpty
}
)
module Simple =
open Fable.Form.Simple
open Fable.Form.Base
let disable =
Base.disable
When writing Fable.Form I discovered the .fsi file feature of F#
I liked the fact that it made everything private by default, however I am wondering if this not confusing potential readers/contributors
It also makes the code navigation less friendly
Should I remove them?
When the user submits the form with one or more invalid fields, these fields are rendered with an error. For short forms this is how the user gets the feedback about the errors. However, if the form is long, such invalid fields, while still rendered correctly, may be above the fold and therefore there is no visual feedback to the user that the form is invalid.
Is there a mechanism to get the information about the form being invalid in the current implementation? Either similar to the Success message
mechanism or some other way that would allow one to render the warning near the submit button or react in some other way.
Adding the instruction to Directory.Build.props does nothing... it should be put in the Directory.Build.targets file...
The current validation strategies offered in Fable.Form.Simple are ValidateOnBlur
and ValidateOnSubmit
. Based on their names, I assumed that they would only validate when a field is blurred or the form is submitted. However, the behaviour instead seems to be that validation is first triggered after blur/submit, but is then triggered after every subsequent change to a field. I would like an option that results in validation only being triggered on submit.
I propose that the following would be suitable cases for the Fable.Form.Simple.Form.View.Validation
type:
ValidateImmediately
(trigger validation after every field state change)ValidateOnBlurThenImmediately
(currently known as ValidateOnBlur
)ValidateOnBlurOnly
(trigger only after blur, not while still focused on a field)ValidateOnSubmitThenImmediately
(currently known as ValidateOnSubmit
)ValidateOnSubmitOnly
(trigger only when submitting, not before)Another possible case could be ValidateOnSubmitThenOnBlur
, but my guess is that that wouldn't be very popular.
ValidateOnBlur
and ValidateOnSubmit
could remain in the library for now, but be marked as deprecated, prompting users to swtich to the ...ThenImmediately
case to preserve behaviour.
Assuming that you're happy with the design proposed above, I'd be happy to investigate the ValidateOnSubmitOnly
case, and hopefully make a PR. The other cases could be left for other contributors (or not implemented at all if there's no demand).
Currently Fable.Form.Simple has a strong dependency on React.
It should be possible to remove this dependency so it could be used in any Elmish application even ones running on top of WPF.
And also allow people to use another view layer than React like Snabbdom for example
I'm trying to understand the code but I'm having a hard time groking it. Could you provide a sample on how to create like simple asHtml
with no dependencies and just pure HTML? I'm trying to use Fable.Lit in this scenario.
Currently Fable form is using the label
of the field to keep track of their errors.
But I am not sure if this is the correct ways of doing it, I feel like we should explicitly ask the user for a unique ID and then have it provide the label of the field.
For example, this cause problem is you change how the checkbox is defined to accept either a string
or a ReactElement
for its "label"
type Attributres =
| Text of string
| ReactElement of ReactElement
Then in the case of ReactElement
we don't have the needed information to store the key
of the field error. We need to change it to ReactElement of string * ReactElement
.
This could be seen as a specific but I think it just shows that we have a wrong design in the current way we consider the forms.
ATM to manipulate a Fable.Form.Simple.Form.View.Model
state we have the following functions:
Form.View.setLoading
But if we want to set the state to Success
, Error _
then we need to update the record directly:
{
model with
Form.State =
Form.View.Success "You have been logged in successfully"
},
Cmd.none,
We also have the function Form.View.idle
which allows to initial the form state to idle by providing the values.
This feels like something is missing and that we have inconsistencies in how these portion of API is designed.
In theory, it should be possible to make Fable.Form works outside of Elmish.
The base package of Fable.Form don't have a dependency on Elmish only the view does to get access to Dispatch
which is used to send the new form representation.
I think it should be possible to make Fable.Form support both Elmish and Hooks.
This means that if someone copy/paste the code it will not work in their project.
Subject...
What is the reason why the onSubmit
payload is not of the type Values
? For example, if I have:
type Values =
{ Name : string
Email : string }
and the two corresponding fields defined in the form, the onSubmit
will be defined as let onSubmit name email = ...
.
Why use the list of fields here and not the Values
type? Similar to the Value
field function in the field record definition (e.g. Value = fun values -> values.Name
).
I'm still struggling to understand how the library works internally so any insight into this part would be great. Thank you!
let disableIf (disabled: bool) (form: Form<'Values, 'A, 'Attributes>)
Profit also to adapt the logic to how Bulma see a form
Hi, I am trying to create a barebones Fable.Form Project with absolute minimal dependencies, nothing that feels like magic, and a scriptable repeatable process.
I am getting the following errors when I run npm start.
Here are the repo steps
dotnet new fable-empty -n skeleton
dotnet add package Fable.Form.Simple.bulma
dotnet new tool-manifest
dotnet tool install paket
dotnet tool restore
dotnet paket add Fable.Form.Simple
Then I over write App.fs with
module App
open Elmish
open Fable.Form.Simple
open Fable.Form.Simple.Bulma
type Values =
{
Email : string
Password : string
RememberMe : bool
}
type Model =
Form.View.Model<Values>
type Msg =
// Used when a change occure in the form
| FormChanged of Model
// Used when the user submit the form
| LogIn of string * string * bool
let init () =
{
Email = ""
Password = ""
RememberMe = false
}
|> Form.View.idle
, Cmd.none
let update (msg : Msg) (model : Model) =
match msg with
// We received a new form model, store it
| FormChanged newModel ->
newModel
, Cmd.none
// The form has been submitted
// Here, we have access to the value submitted from the from
| LogIn (_email, _password, _rememberMe) ->
// For this example, we just set a message in the Form view
{ model with
State = Form.View.Success "You have been logged in successfully"
}
, Cmd.none
let form : Form.Form<Values, Msg> =
let emailField =
Form.textField
{
Parser =
fun value ->
if value.Contains("@") then
Ok value
else
Error "The e-mail adress must contain a '@' symbol"
Value =
fun values -> values.Email
Update =
fun newValue values ->
{ values with Email = newValue }
Error =
fun _ -> None
Attributes =
{
Label = "Email"
Placeholder = "[email protected]"
}
}
let passwordField =
Form.passwordField
{
Parser = Ok
Value =
fun values -> values.Password
Update =
fun newValue values ->
{ values with Password = newValue }
Error =
fun _ -> None
Attributes =
{
Label = "Password"
Placeholder = "Your password"
}
}
let rememberMe =
Form.checkboxField
{
Parser = Ok
Value =
fun values -> values.RememberMe
Update =
fun newValue values ->
{ values with RememberMe = newValue }
Error =
fun _ -> None
Attributes =
{
Text = "Remember me"
}
}
let onSubmit =
fun email password rememberMe ->
LogIn (email, password, rememberMe)
Form.succeed onSubmit
|> Form.append emailField
|> Form.append passwordField
|> Form.append rememberMe
let view (model : Model) (dispatch : Dispatch<Msg>) =
Form.View.asHtml
{
Dispatch = dispatch
OnChange = FormChanged
Action = "Sign in"
Validation = Form.View.ValidateOnSubmit
}
form
model
Then
npm install
npm start
And i get
ERROR in ./.fable/Feliz.1.40.0/Interop.fs
Module not found: Error: Can't resolve 'react' in 'C:\skeleton.fable\Feliz.1.40.0'
@ ./.fable/Feliz.1.40.0/Interop.fs 7:0-38 8:0-26 258:34-39 259:38-51
@ ./.fable/Fable.Form.Simple.Bulma.1.1.0/Form.fs
@ ./src/App.fs
@ ./src/App.fsproj
i 「wdm」: Failed to compile.
Error from chokidar (C:): Error: EBUSY: resource busy or locked, lstat 'C:\DumpStack.log.tmp'
Error from chokidar (C:): Error: EBUSY: resource busy or locked, lstat 'C:\hiberfil.sys'
Error from chokidar (C:): Error: EBUSY: resource busy or locked, lstat 'C:\pagefile.sys'
Error from chokidar (C:): Error: EBUSY: resource busy or locked, lstat 'C:\swapfile.sys'
Error from chokidar (C:\node_modules): Error: EBUSY: resource busy or locked, lstat 'C:\DumpStack.log.tmp'
Error from chokidar (C:\node_modules): Error: EBUSY: resource busy or locked, lstat 'C:\hiberfil.sys'
Error from chokidar (C:\node_modules): Error: EBUSY: resource busy or locked, lstat 'C:\pagefile.sys'
Error from chokidar (C:\node_modules): Error: EBUSY: resource busy or locked, lstat 'C:\swapfile.sys'
I am trying to publish a Material-UI
implementation for Fable.Form.Simple. The project compiles and everything looks good, but when I add a reference to it from another project (via Nuget) I get:
client: C:/Users/Terence/Projects/Safe-Playground/src/Client/Index.fs(202,29): (210,47) error FSHARP: The type referenced
through 'Fable.Form.Simple.Form.View.ViewConfig`2' is defined in an assembly that is not referenced. You must add a reference
to assembly 'Fable.Form.Simple'. (code 74)
I have added the reference to Fable.Form.Simple in my paket.dependencies
, even added an open
to the top of both my fsi and fs file (compiler is complaining that it is not necessary), but I am not able to add the reference to the implementation.
I feel like a complete idiot for not seeing where I am missing the reference and what I am doing wrong, any advise - (even if you just tell me where to look please) would be highly appreciated!
Signature would be
let disableWhen
(condition: 'Values -> bool)
(form: Form<'Values, 'A, 'Attributes>)
: Form<'Values, 'A, 'Attributes>
=
Base.disableWhen condition form
I am unsure if we should add this helpers or if this would lead to bad practice in the library code.
Currently, attributes are exposed using records only meaning that we need to provides all the properties all the time.
Attributes = {
Label = "Order Value"
Placeholder = "Order Value"
HtmlAttributes = []
}
This is annoying because we need to provide information that we don't care about.
For example, if you have a DatePickerField
you could have attributes looking like that:
type Attributes = {
Label: string
DisplayMode: DisplayMode
ShouldDisableDate: System.DateTime -> bool
ShouldDisableMonth: System.DateTime -> bool
ShouldDisableYear: System.DateTime -> bool
}
Forcing the user to provide all the ShouldDisableXX
functions, even when he don't want to disable any.
Exposing an alternative API would allow us to work around this problem:
Form.datePickerField {
Parser =
fun value ->
match value.SelectedDate with
| Some date -> Ok date
| None -> Error "This field is required"
Value = _.CollectionDate
Update =
fun newValue values -> {
values with
CollectionDate = newValue
// Reset the time slot when the date changes
CollectionTimeSlot = ""
}
Error = fun _ -> None
Attributes =
DatePickerField.Attributes.create "Collection Date"
|> DatePickerField.Attributes.withDisplayMode DatePickerField.DisplayMode.Default
|> DatePickerField.Attributes.withShouldDisableDate (fun date ->
timeSlots
|> List.exists (fun slot -> Date.getDayKey slot.Start = Date.getDayKey date)
|> not
)
}
Thoth.Elmish.FormBuilder
old comparaison of the different styleToday, I think I lean more toward pipeline builders.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.