Get Started
Please check the samples for a quick start
Document site source code: https://github.com/slaveOftime/Fun.Blazor/tree/master/Fun.Blazor.Docs.Wasm.
Templates, also with more samples in it: https://github.com/slaveOftime/Fun.Blazor.Samples.
Use dotnet templates:
👈 always try to use the latest one.
dotnet new --install Fun.Blazor.Templates::4.1.1
dotnet new fun-blazor -o FunBlazorDemo1
Code structure example (just my opinionated way)
If you prefer blazor csharp official style, you can just use fun-blazor template to get started.
This project supports multiple patterns for state management. From my experience, it is not good to use Elmish for your whole project because of the performance and state share concern. Sometimes, it is a little verbose.
You can try this:
Db
Domain
Services
UI
|--- Stores.fs // contains shared store or global store
type IShareStore with // scoped for the session in blazor server mode
member store.IsDark = store.CreateCVal("IsDark", true)
type IGlobalStore with // Singleton store, shared for all. Used in server-side blazor to share some data for all connected users.
...
|--- Hooks.fs // standalone UI logic
type IComponentHook with
member hook.TryLoadPosts(page) = task {
...
}
member hook.UseSettingsForm() =
hook
.UseAdaptiveForm({| Name = "foo"; ... |})
.AddValidators(...)
.AddValidators(...)
|--- Controls.fs // Some small shared controls
|--- Comp1.fs // Your business component
// Make your fragment smaller, so you can compose it in a cleaner way and get better inline optimization, hot-reload speeding, and intellisense performance
let private fragment1 = div {...}
let private fragment2 (shareStore: IShareStore) =
adaptiview {
let! isDark, setIsDark = shareStore.IsDark.WithSetter()
div { ... }
}
// Or use Elmish if you like
let private fragment3 = html.elmish (init, update, view)
type Comp1 =
// So we can provide overloads for future iteration
static member Create() =
html.inject (fun (svc1, shareStore: IShareStore, ...) ->
div {
fragment1
fragment2 shareStore
fragment3
}
)
|--- Comp2.Hooks.fs // in case you have a large component, or you can even create a separate folder for the whole component
|--- Comp2.Control1.fs // manage a large control which is only for your business Comp2
|--- Comp2.fs // The entry for your comp2
|--- App.fs // compose your components or pages
let private routes =
html.route [
routeCi "/page1" (Comp1.Create())
routeAny (Comp2.Create())
]
let app =
div {
header
routes
footer
}
|--- Index.fs // if you are using blazor server mode, you need to have this. You can check the template.
|--- Startup.fs