Code Monkey home page Code Monkey logo

sutil's Introduction

Sutil Nuget

Sutil is a web application framework for F#.

Its features are:

  • Simple DOM builder, courtesy of Feliz.Engine
  • No dependencies. Sutil is written entirely in F#, and so does not layer on top of another JS framework, such as React.
  • Reactivity using IObservable and stores. Sutil does not use a virtual DOM.
  • Support for Elmish (Model-View-Update) architecture.

In addition, Sutil inherits all the benefits of both Fable (F# with excellent JS interop) and F# itself.

Sutil was heavily inspired by Svelte, and imports several of its design features, such as stores and component styling. Some parts of Sutil are direct ports from Svelte.

Development

To compile Sutil and build the main Sutil app in watch mode:

npm run start

To run tests:

npm run test

To deploy to https://sutil.dev (you will need to be Dave Dawkins for this to work). This will:

  • build Sutil
  • build documentation
  • install to sutil.dev
npm run deploy:linode

Building the REPL

Manually:

  • ensure that repl/src/Fable.Repl.Lib/Fable.Repl.Lib.fsproj is up-to-date with the list of Sutil file names.
  • review repl/public/samples/samples.json for examples that should be included or removed

Build the REPL and deploy (to sutil.dev if you're Dave Dawkins):

cd ../davedawkins/repl
./sutilbuild.sh
npm run deploy:linode

sutil's People

Contributors

alfonsogarciacaro avatar alkasai avatar angelmunoz avatar davedawkins avatar dejanmilicic avatar jlll1 avatar pierreyvesr avatar s0kil avatar sajagi avatar

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  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  avatar  avatar

Watchers

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

sutil's Issues

Rename IStore.Get to IStore.Value

If I'm not mistaken, the convention in .NET is to use names for properties and verbs for methods. So I guess many users will think Get must be called as a method (as in myStore.Get()). What do you think?

Getting Started docs

Maybe i am doing something daft or these are out of date

On (https://sutil.dev/#documentation-from-a-template)
dotnet new install Sutil.Templates
returns
Sutil.Templates could not be installed, the package does not exist.

And

On (https://sutil.dev/#documentation-from-scratch)
after also running npm install and npm run start
C:/Users/harry/StaticAuth/src/App.fs(3,6): (3,11) error FSHARP: The namespace or module 'Sutil' is not defined. (code 39)
C:/Users/harry/StaticAuth/src/App.fs(5,14): (5,18) error FSHARP: The value, namespace, type or module 'Html' is not defined. (code 39)
C:/Users/harry/StaticAuth/src/App.fs(7,11): (7,18) error FSHARP: The value, namespace, type or module 'Program' is not defined. (code 39)

Am running dotnet 6.0.401 on windows 11

Sutil without fable (aspnetcore only)

I was wondering if i can integrate sutil in a standard aspnetcore MVC app (server side rendered) from the www root folder, without requiring/using fable at all.

At first I thought that we might make use of a Fable compiler plugin to generate boilerplate,  
but it turns out that F# does a pretty good job of that itself.

Is the app.js file generated even without fable.js but purely including sutil package?

if so maybe adding a copy to the wwwroot folder would already make it work also for server aspnetcore? thanks have a great day and amazing project ๐Ÿฅ‡ ๐Ÿ” ๐Ÿ† !

maybe if this is possible it could be worth a template , like for server side rendering only (when client reload doesnt matter much)

Remove bulma dependency?

Hi, thank you for the great library, finally I am able to write F# code without using elmish! Can you please provide example of how to use another CSS framework, rather than bulma (I'm mostly interested in tailwindcss at the moment)? I would also recommend leaving bulma as opt-in dependency rather than hard dependency for Sutil. It seems some support has already been done for Fable and Feliz.

Bind.each requires F# list instead of array

Hello. I've been attempting to write a sample app using this, and was wondering about Bind.each requiring an F# list instead of the more general seq. As I understand Fable, F# lists get transpiled using a special list.js helper library from fable, instead of the native JavaScript array, whereas .Net arrays do get transpiled to JS arrays.

Is there a specific reason Bind.each requires a list? I would like to be able to use the JS array in my fable app, both for familiarity on how it behaves, as well as avoiding the extra import if possible.

e.g.:

    let tags: IStore<string array> = Store.make [| "one"; "two" |]
    let otherTags: IStore<string list> = Store.make [ "one"; "two" ]

    Html.div [
        disposeOnUnmount [
            tags
            otherTags
        ]
        Bind.each (tags, (fun tag -> Html.div [ text tag ])) // This one is compiler error
        Bind.each (otherTags, (fun tag -> Html.div [ text tag ])) // This one works

    ]

thanks

Feature Request: createEventDispatcher

Rather than keep tweeting about it Reference from earlier

Svelte provides an event dispatcher based on CustomEvents I think this can be a great addition particularly for Library authors and users, this allows users to emit events from their components and let them listen for them in an ergonomic way in Sutil on "my-event eventHandler []" rather than than drilling callbacks or resort to third party thigs like Stores which may not be what you want to rely to if you are authoring components (eg. A calendar emitting a on-calendar-open kind of event)

As pointed out in that discussion there's already a few things we can use to reduce boilerplate
https://github.com/davedawkins/Sutil/blob/main/src/Sutil/DOM.fs#L328

what seems to be missing there is how the user can get a reference to the current element which in JS is usually like this.dispatchEvent(name, opts)

with some pointers I'd be willing to give it a shot at implementing this (but it can take a while since I'm moving next week)

edit: Seems bind:this is what I might be looking for to ease some of the boilerplate

New nuget release including Bind.radioValue ?

I've just updated my code to Sutil 2 from version 1.
It's been fairly smooth except for radio groups: the current nuget package doesn't include Bind.radioValue, so I had to build against a local copy of the latest code.
When do you expect to do a new nuget release?

I also found that I was using quite a few functions from the Interop module that is now Internal - so I just had to roll out my own.

CRUD example can get confused about list selection

To reproduce:

  1. Update a record (might not be necessary, just what I did)
  2. Hit delete (deletes record you just updated)

New record appears to be selected (because Name and Surname fields populated) but no selection shown.
Attempting to select a record causes list to deselect immediately

Using a web component multiple times overrides prop values

When you define a web component and use it more than once the last initialization wins over the previous ones, in the repl if you click the first counter it will start at 100 rather than 0, the second counter starts at 100 as expected

As an aside: Sutil Styling doesn't work with Sutil Web components as seen in the repl above this is mainly because the Shadow DOM already encapsulates the CSS styles so the way Sutil appends styles to the head of the document will not work, this is just a heads up in case someone faces head on with this

minor styling nit on sutil.dev

Hi,

I saw a small css update it might be worth mentioning.

55F1D0DD-B29B-48C3-8FD7-DF0B8390816C

When scrolling the code panel on the RHS, it also scrolls the LHS menu and drags it up, when it should probably stay in place.

If you set overflow-x and possibly overflow-y to "scroll" in the CSS for the RHS pane, I think it should be good - hope this is helpful.

cheers

Expose host to web components

Many things in web components work with the class that creates the web component for example Fable.ShadowStyles allows setting constructable stylesheets on web components BUT they need to have access to the shadow root of the element

I propose to change the function inside WebComponents.fs for the following one

let registerWebComponent<'T> name (ctor : IStore<'T> -> HTMLElement -> SutilElement) (init : 'T) : unit =

    let wrapper (host:Node) : WebComponentCallbacks<'T> =
        let model = Store.make init
        let result = ctor model host // this change right here
        let disposeElement = DOM.mountOnShadowRoot result host

        let disposeWrapper() =
            model.Dispose()
            disposeElement()

        {   Dispose = disposeWrapper
            GetModel = (fun () -> model |> Store.current)
            SetModel = Store.set model }

    makeWebComponent name wrapper init

then we would be able to do something like the following

module Components.Counter

open Fable.Core
open Fable.Core.JsInterop
open Sutil
open Sutil.DOM
open Sutil.Attr
open Sutil.WebComponents

open ShadowStyles
open ShadowStyles.Operators
open Browser.Types

type private ComponentProps = {| init: int |}

let private styles =
  // this is part of shadow styles
  [ "button" => [ SCss.backgroundColor "#FFCC00" ]
    "div" => [ SCss.color "#FF00FF" ] ]

let private Counter (props: Store<ComponentProps>) (host: HTMLElement) =
  // ShadowStyles can set the constructable stylesheets to the webcomponent
  ShadowStyles.adoptStyleSheet (host, styles)
  let count = props .> (fun p -> p.init)
  let initVal = props |-> (fun props -> props.init)
  let getCount () = props |-> (fun props -> props.init)

  Html.div [
    disposeOnUnmount [ props ]
    Bind.fragment count (fun counter -> Html.text $"{counter}")
    Html.br []
    Html.button [
      onClick
        (fun _ ->
          props
          <~= (fun props -> {| props with init = getCount () + 1 |}))
        []
      Html.text "Increment"
    ]
    Html.button [
      onClick
        (fun _ ->
          props
          <~= (fun props -> {| props with init = getCount () - 1 |}))
        []
      Html.text "Decrement"
    ]
    Html.button [
      onClick
        (fun _ ->
          props
          <~= (fun props -> {| props with init = initVal |}))
        []
      Html.text "Reset"
    ]
  ]

let register () =
  registerWebComponent "su-counter" Counter {| init = 0 |}

which would result in this
image

this is the main reason why I primarily used classes in this PR https://github.com/davedawkins/Sutil/pull/43/files#diff-469049174da5c0501dc98ae73a9c8a7b17aa9c7abead51ee31221916da6142cbR27 but I still kept the function call inside the web component rather than delegating the function call to other places, with Fable is hard to keep track of "this", in this case it can be fixed easily by providing the host as a parameter.

Also another very important aspect is event targets, Web components should dispatch events when they are affected by user input, so events should ideally be dispatched from the web component itself rather than a button or another element inside the web component, for more context check fable-compiler/Fable.Lit#14

we could also expose an init function that gives you the host one time instead to do these kinds of things.

Why not to include ShadowStyles into fable? Constructible Stylesheets are not available in all browsers yet, so this has to be polyfilled in browsers that are not chromium based but they are the most performant and simple means to have shared stylesheets for web components otherwise Sutil would have to find a way to apply styles to Sutil Elements

Weird behavior when working with Cmds

Hi,

In StonkWatch, branch: update-sutil

Using Sutil 1.0.0-alpha-005

I added a Cmd with AsyncMsg.

type Model =
  { Portfolio: Portfolio
    CurrentPortfolioTab: PortfolioTab }

type Message =
  | SelectedPaneChanged of PortfolioTab
  | FetchPortfolio
  | PortfolioFetched of Portfolio
  
let init (): Model * Cmd<Message> =
  { Portfolio = { Positions = [] ; Balances = Undefined }
    CurrentPortfolioTab = Positions }, Cmd.ofMsg FetchPortfolio

let update (msg: Message) (model: Model): Model * Cmd<Message> =
  match msg with
  | SelectedPaneChanged portfolioTab ->
      let model =
        if portfolioTab <> model.CurrentPortfolioTab then
          { model with
              CurrentPortfolioTab = portfolioTab }
        else
          model
          
      model, Cmd.none
      
  | FetchPortfolio ->
    let msg = async {
      do! Async.Sleep 2000
      return PortfolioFetched SeedData.portfolio
    }
    model, Cmd.OfAsync.result msg
      
  | PortfolioFetched portfolio ->
    { model with Portfolio = portfolio }, Cmd.none

View function is a bit long, will not include.

This is the behavior I am getting this:

2021-03-22 12-56-30

Basically, when I click back and forth between the tabs, the tables that get created before the 2 seconds with just stay there and not get cleaned up.

Not sure if I am doing something wrong in the code, any help appreciated!

RFC: Web Component API

RFC - Web Components API

Summary

Since Sutil doesn't have any frontend library dependency (other than Fable libraries) it should be possible to register Sutil nodes as custom elements. These would allow Sutil users to author component libraries in a way that they will be able to be consumed in any browser environment, framework, library knowing they are backed by the safety of F#

Design

Nothing is set in stone but ideally I'd be looking to offer an API like this

[<WebComponent("my-element")>]
let MyElement (el: HTMLElement, props: ElementProps) =
    let hidden = Store.make props.hidden
    Html.div [
        Bind.attr("hidden" hidden)
        text $"My Element's message: {props.message}"
    ]

this should generate/emit a component that would be similar in functionality (not in code) as the following example

https://stackblitz.com/edit/js-vfmi1a?devtoolsheight=33&file=index.js

Since Sutil view functions are evaluated once we might not need to handle

Drawbacks

  • Custom Elements are defined as classes

    This might be troublesome since we'd ideally want to stick to a functional approach but I believe we can get

Unresolved questions

  • Should we handle shadow DOM?

  • How do we handle attribute callbacks? (AFAIK Sutil views are evaluated once)

  • Should we expose the element instance (this) as a context object?

  • Should we expose functionality related to lifecycle hooks?

    • connectedCallback
    • disconnectedCallback
    • adoptedCallback
    • attributeChangedCallback
  • Should this be in Feliz.Engine instead? (cc @alfonsogarciacaro)

Links And References

Sveltish needs its own name?

As suggested by @alfonsogarciacaro , Sveltish could use its own identity. This will encourage its growth beyond its initial inspiration, which is undoubtedly Svelte.

Some initial plays on the word "Svelte":

  • Belto (Esbelto is Spanish for "svelte") (edit: correction to Esbelto)
  • Langsing (Indonesian for "svelte/slim")
  • Pico / Nano (small - Sveltish is relatively small for what it does. HelloWorld is around 26kb)
  • <some random word that doesn't need to mean anything at all>

Aspects of Sveltish to consider:

  • Small (hence belto/langsing/pico/nano etc)
  • Self-contained / no dependencies (eg, it's not using React)
  • F# / functional
  • Batteries-included front-end dev for Fable
  • Supports MVU (Elmish / Elm)
  • It's (another!) front-end framework

Testing sutil app

Hi there!
Thank You for great work on Sutil. I wanted to develop small app using beta version but I struggle to setup tests :( I am hoping to get some help.

  1. I've stolen TestFramework.fs from Sutil repository.
  2. The test looks like this;
module Tests.Tests

open TestFramework
open Sutil

let tests = testList "Sutil.DOM" [

    // Simplest case
    testCase "Hello World" <| fun () ->
        let app =
            Html.div "Hello World"

        mountTestApp app

        Expect.queryText "div" "Hello World"
        Expect.areEqual(1, 1)
]
  1. Commands I use (stolen from sutil repo):
    "tests-console": "mocha dist/tests -r esm",
    "watch:tests": "dotnet fable watch tests -o dist/tests --runWatch mocha dist/tests -r esm",
    "tests": "dotnet fable tests --run webpack --config webpack.config.tests.js",
    "start:tests": "dotnet fable watch tests --run webpack serve --config webpack.config.tests.js "

The best what I get after running start:tests is attached on the screen:
image
So it is empty. When I run tests:watch I get:

> watch:tests
> dotnet fable watch tests -o dist/tests --runWatch mocha dist/tests -r esm

Fable: F# to JS compiler 3.2.9
Thanks to the contributor! @JacobChang
tests> dotnet restore Tests.fsproj
  Determining projects to restore...
  All projects are up-to-date for restore.
Parsing tests/Tests.fsproj...
Initializing F# compiler...
Compiling tests/Tests.fsproj...
F# compilation finished in 5621ms
Fable compilation finished in 1392ms
.> node_modules/.bin/mocha dist/tests -r esm
Watching .
logging:init defaults


  0 passing (1ms)

When I run test-console I get;

> tests-console
> mocha dist/tests -r esm

logging:init defaults


  0 passing (0ms)

my webpack.config.tests.js looks like this;

var path = require("path");

module.exports = {
    mode: "development",
    entry: "./tests/Tests.fs.js",
    output: {
        path: path.join(__dirname, "./tests/public"),
        filename: "test-bundle.js",
    },
    devServer: {
        contentBase: "./tests/public",
        port: 8080,
    },
}

I have the repo here: https://github.com/marcingolenia/kabanos if You need more information.

Can You give me some hints on how to move forward with this? Thanks in advance :)

Unwanted each behaviour

Hi, I'm seeing an unwanted behavior of html elements reordering. Repro:

module App

open Sutil
open Sutil.DOM
open Sutil.Attr

let view() =
    let store = [ "one"; "two"] |> Store.make

    Html.div [
        each store (fun item ->
            Html.div [
                Html.div [
                    text item
                ]
            ]
        ) []
        Html.button [
            text "Add item"
            onClick (fun e ->
                store.Update id
            ) [ PreventDefault ]
        ]
    ]
view() |> mountElement "sutil-app"

Once you click on button, it appears on the top of the list
image

Link to github source leads to 404

Clicking on

image

with href

https://github.com/davedawkins/Sutil/src/Sutil/DOM.fs#L1217-1217

leads to Not Found.

A link that does work is

https://github.com/davedawkins/Sutil/blob/main/src/Sutil/DOM.fs#L1217-1217

The difference is the blob/main/ insert. How did I fix this?

Compatibility with code produced from Html2Feliz

I tested it and we are still missing these two

  1. Html.svg
  2. prop.children

example usage of children is like this

            Html.aside [
                prop.classes [ "fixed"; "z-50"; "md:relative" ]
                prop.children [
                    Html.input [
                        prop.type' "checkbox"
                        prop.classes [ "peer"; "hidden" ]
                        prop.id "sidebar-open"
                    ]
                ]                

License?

Hey ๐Ÿ‘‹

maybe I'm super blind right now, but does this project not have a license?

Avoid eval

let classCtor = eval(ctorJs);

I think this won't pass security considerations due to CSP I'd suggest avoid eval and try something different, the class used for the web component doesn't need to match the name with the name in the registry classes can be anonymous in Javascript

    let className = name.replace(/-/g, '');
    let ctorJs = `
        let ${className} = function() {
            let _ = Reflect.construct(HTMLElement,[], ${className});
            return init(_, attributes);
        };
        ${className}.observedAttributes = attributes;
        ${className};
    `;

could be translated to

let ctorJs = class {
  static get observedAttributes() { return attributes; } 
  attributeChangedCallback( name, oldVal, newVal ) {
        this[name] = newVal;
    }
  connectedCallback() {
        for (const key of attributes) {
            if (this.hasAttribute(key)) {
                this[key] = this.getAttribute(key);
            }
        }
    }
  disconnectedCallback () {
        this.sutilCallbacks.Dispose();
    }
} 

customElements.define(name, ctorJs);

If we're on a javascript file there's no need to avoid JS classes, if we're doing this inside F# then the func version would be preferred but even then eval should be avoided for security concerns

lazy loading/bindPromise

Sorry @davedawkins, haven't checked the whole API but, is there something to bind promise/transform promises into SutilElements? I assume it shouldn't be very difficult as SutilElements are asynchronous by default. Binding promises would enable lazy loading and deferred elements (for fetching data, etc).

The helper should have 3 arguments:

  • The promise: element is automatically updated when the promise is resolved
  • Fallback (optional?): What to show while the promise hasn't resolved
  • OnError (optional?): What to show if the promise fails

Any ideas for a proper Bulma integration?

Hi,

We can currently use Bulma via css classes, but I am wondering how could we make a proper Bulma integration ร  la Feliz.Bulma?

Any plans on making first-class styling integrations?

Bunch of css properties missing

I've been noticing that there are some css properties missing in Sutil, for example align-items, place-self etc.
I wonder if this is done on purpose? Is Sutil trying to limit the CSS api, push the developers towards certain approaches, while not exposing the others?
If not, then then adding missing CSS properties to Sutil is something I'd gladly investigate and implement.

Set Attribute vs Set Property

Right now Sutil sets properties for HTML Elements when using the Binding utilities and particularly everything that uses Interop.set

[<Emit("$0[$1] = $2")>]
let set<'T> (ob:obj) (name:string) (value:'T) : unit = jsNative

This works fine for single named properties but for custom elements, attributes are dash-cased meaning that this will only set properties on elements and this is not what should be done for attributes

Bind.attr("my-attribute", observable)

ends up as

ctx.ParentNode["my-attribute"] =  value

A simple workaround is to use a camel cased name instead

Bind.attr("myAttribute", observable)

But, please note that not every attribute corresponds to the same camel cased property (elements can decide wheter to use the same property or a different one when attributes change)

Instead using Interop.set for attributes we should use el.setAttribute(attr, stringValue)

so we could do the following

Bind.attr("my-attribute", observable)
ctx.ParentNode.setAttribute("my-attribute", stringValue)

and also adding a new API for properties which is a valid use case (bind to properties rather than attributes)

Bind.prop("myAttribute", observable)
Interop.set propName value

Documentation List

I think good documentation will always attract devs, so here's a list of things that we could start tracking (feel free to add more) with the documentation

For that I think we can grab inspiration of Vue Guide, Lit docs, and imba docs

Vue is really good at explaining the whole in/outs of their framework and Lit is quite concise and short, it lacks some of the extended approach of vue, but I think a middle ground for Sutil could be really good

Introduction

  • What is Sutil - WIP
  • Getting Started - WIP
    • Dotnet templates
    • GH templates (useful for exploration not just getting started) - WIP
  • Why/Why not use it

Concepts

  • Syntax
  • Lists - WIP
  • Forms - WIP
  • Classes/Styles - WIP
  • Simple binds - WIP
  • Events - WIP

In-Depth

  • Styling
  • Life Cycle
  • Events
  • Binding
  • Stores
  • Rendering
  • Custom Events
  • Web Component Interop

Transitions - Animations

(I'm not really familar with this so if you can put something here it would be good)

Advanced (perhaps not the best word)

  • Browser Requirements

  • Testing

  • Integration with other parts of the stack

    • SAFE
    • ASP.NET
  • Using Bundlers

    • Webpack
    • Snowpack (I can take this one)
    • Vite? (I think Alfonso was experimenting with this a few months ago)
    • Parcel?
  • Deployment

    • Github Pages
    • Firebase (I can take this one)

There are a couple of those that already exist or can be adapted from the current examples

Props never get updated in WebComponent with elmish

let MyComponent (props : IStore<Props>) =
    let store, dispatch = Store.makeElmish Model.init update ignore props.Value
    use propsSubscription = props.Subscribe (PropsChanged >> dispatch)

In above code, PropsChanged message will always get delivered with initial value of props.
Events get fired, but value of props is always the same.

Normal IStore<Props> |> Store.map rendering code appears to work fine (below): Html text is changing correctly.
Just elmish (above) never sees any change.

    Bind.el(props |> Store.map (fun m -> m.text), Html.text)

Plans for SSR?

Hello, I know this project is in its infancy, but it already seems really cool.
Something I'm personally interested in, is Server Side Rendering of client side components which can then be hydrated. Are there any plans with this project to support that?

Since a Feliz View engine is coming, it might be possible to use their mechanisms.

Thanks.

Elmish performance improvements?

Hey, thanks for sharing Sutil. I've been enjoying it a ton.

I happen to be writing something that requires a spreadsheet-like feature, and having come from Fable.Elmish, the spreadsheet sample happens to be a perfect reference for me.

But not surprisingly, performance seems to be quite slow, presumably because it has no shadow DOM and has to rebuild everything within a Bind.el.

Is there anything I can do to speed up MVU views? Or should I just switch to a reactive design?

Bug report: Error when adding sutil 1.0.0-alpha-006 to SAFE template

Os and SDK versions

lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.2 LTS
Release:	20.04
Codename:	focal
dotnet --version
5.0.201

Steps to reproduce the error

1 - Change the SAFE template to the 3.0.0-beta001. To do so, I've just installed the template locally using:

dotnet new -i SAFE.Template::3.0.0-beta001

2 - Create a new SAFE project using the template:

mkdir bug_report
cd bug_report
dotnet new SAFE

3 - Restore the project and run

dotnet tool restore
dotnet run

Until here, everything goes ok.

4 - Instal the last version of Sutil via nuget

dotnet paket add Sutil --version 1.0.0-alpha-006

Then, try to run the project and in the Client compilation the following error will happen:

/home/iago-moreira/Desktop/bug/src/Client/.fable/Sutil.1.0.0-alpha-006/Bulma.fs(19,9): (22,10) error FSHARP: No overloads match for method 'div'.

Known type of argument: NodeFactory list

Available overloads:
 - static member Html.div : children:#seq<Fable.React.ReactElement> -> Fable.React.ReactElement // Argument 'children' doesn't match
 - static member Html.div : value:Fable.React.ReactElement -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : value:float -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : value:int -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : value:string -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : xs:IReactProperty list -> Fable.React.ReactElement // Argument 'xs' doesn't match (code 41)
/home/iago-moreira/Desktop/bug/src/Client/.fable/Sutil.1.0.0-alpha-006/Bulma.fs(21,13): (21,30) error FSHARP: No overloads match for method 'select'.

Known type of argument: NodeFactory list

Available overloads:
 - static member Html.select : children:#seq<Fable.React.ReactElement> -> Fable.React.ReactElement // Argument 'children' doesn't match
 - static member Html.select : xs:IReactProperty list -> Fable.React.ReactElement // Argument 'xs' doesn't match (code 41)
/home/iago-moreira/Desktop/bug/src/Client/.fable/Sutil.1.0.0-alpha-006/Bulma.fs(31,53): (31,139) error FSHARP: No overloads match for method 'div'.

Known type of argument: NodeFactory list

Available overloads:
 - static member Html.div : children:#seq<Fable.React.ReactElement> -> Fable.React.ReactElement // Argument 'children' doesn't match
 - static member Html.div : value:Fable.React.ReactElement -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : value:float -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : value:int -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : value:string -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.div : xs:IReactProperty list -> Fable.React.ReactElement // Argument 'xs' doesn't match (code 41)
/home/iago-moreira/Desktop/bug/src/Client/.fable/Sutil.1.0.0-alpha-006/Bulma.fs(31,93): (31,137) error FSHARP: No overloads match for method 'select'.

Known type of argument: NodeFactory list

Available overloads:
 - static member Html.select : children:#seq<Fable.React.ReactElement> -> Fable.React.ReactElement // Argument 'children' doesn't match
 - static member Html.select : xs:IReactProperty list -> Fable.React.ReactElement // Argument 'xs' doesn't match (code 41)
/home/iago-moreira/Desktop/bug/src/Client/.fable/Sutil.1.0.0-alpha-006/Bulma.fs(73,19): (73,54) error FSHARP: No overloads match for method 'i'.

Known type of argument: NodeFactory list

Available overloads:
 - static member Html.i : children:#seq<Fable.React.ReactElement> -> Fable.React.ReactElement // Argument 'children' doesn't match
 - static member Html.i : value:Fable.React.ReactElement -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.i : value:float -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.i : value:int -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.i : value:string -> Fable.React.ReactElement // Argument 'value' doesn't match
 - static member Html.i : xs:IReactProperty list -> Fable.React.ReactElement // Argument 'xs' doesn't match (code 41)
/home/iago-moreira/Desktop/bug/src/Client/.fable/Sutil.1.0.0-alpha-006/Bulma.fs(84,58): (84,62) error FSHARP: No constructors are available for the type 'Html' (code 1133)

How to solve the error (until a new release fix the bug)

1 - Remove the Sutil from you project

dotnet paket remove Sutil 

2 - Install the 0.2.1-alpha version

paket add Sutil --version 0.2.1-alpha

How Sutil works?

Hello @davedawkins!
I just came across your project and what I really like about it is how it does not have any JS dependency to install (as per HelloWorld sample), except for webpack. The docs, however, does not explain it in detail as to how Sutil really works. Could you please explain it works? From what I've understood so far, Svelte compiles HTML + JS + CSS into JS and CSS. Does Sutil too compile F# code to JS? If yes, then how is it different from Fable compiler?

Sorry if the question is not very clear. I just want to understand how Sutil works. Thank you.

Difference between bindElementC and bindElementCO

What's the difference between bindElementC and bindElementCO? Most of the code in the functions is the same except the former calls build (element(next)) while the latter uses build (element(store)).

Feliz.Bulma.DateTimePicker and other extensions

Hi,

How to add properly Feliz.Bulma extensions?

Html.p [
        color.hasTextWhite
        Html.text $"Data wpisu : {Db.KeyName}"
        Feliz.Bulma.DateTimePicker.dateTimePicker [
          dateTimePicker.onDateSelected (fun (d:DateTime option) -> () (* handle here *))
          dateTimePicker.defaultValue DateTime.Now
        ]
      ]

Gives error:
Sutil and ReactElement is not compatible

Kind regards

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.