-
This isn't really a question, more of a note of a 'gotcha', and a check that there's not a way to avoid the pitfall. I made a component that takes an The missing bit was a call to Here's the code with the important line commented-out. (I 'hide' the passed-in namespace FuncUIFileDialog
open System
open Elmish
open Avalonia
open Avalonia.Themes.Fluent
open Avalonia.FuncUI.Hosts
open Avalonia.Controls.ApplicationLifetimes
open Avalonia.Controls
open Avalonia.FuncUI
open Avalonia.FuncUI.DSL
open Avalonia.FuncUI.Elmish.ElmishHook
type Model = { Value : int }
type Msg = | IncrementValue
module MainView =
let handler msg model =
match msg with
| IncrementValue ->
{ model with Value = model.Value + 1}, Cmd.none
let myComponent key (model : IReadable<Model>) dispatch =
Component.create (key,
fun ctx ->
//let model = ctx.usePassedRead model
let flag = ctx.useState false
let value = model |> State.readMap (fun m -> m.Value)
StackPanel.create [
StackPanel.children [
CheckBox.create [
CheckBox.content "Checkbox with local state"
CheckBox.isChecked flag.Current
CheckBox.onChecked (fun _ -> flag.Set true)
CheckBox.onUnchecked (fun _ -> flag.Set false)
]
Button.create [
Button.content "Send increment message"
Button.onClick (fun _ -> dispatch IncrementValue)
]
TextBlock.create [
TextBlock.text $"Value: {value.Current}"
]
]
]
)
let create () =
let initial = { Value = 0 }
Component (
fun ctx ->
let model = ctx.useState(initial)
let _, dispatch = ctx.useElmish (model, handler)
Grid.create [
Grid.rowDefinitions "*"
Grid.children [
ContentControl.create [
Grid.row 0
ContentControl.content (
myComponent "c1" model dispatch
)
]
]
]
)
type MainWindow() =
inherit HostWindow()
do
base.Title <- "FuncUIExperiments"
base.Content <- MainView.create ()
type App() =
inherit Application()
override this.Initialize() =
this.Styles.Add (FluentTheme())
override this.OnFrameworkInitializationCompleted() =
this.Name <- "FuncUIExperiments"
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktopLifetime ->
let mainWindow = MainWindow()
mainWindow.MinWidth <- 850.0
mainWindow.MinHeight <- 600.0
desktopLifetime.MainWindow <- mainWindow
| _ -> ()
module Program =
[<EntryPoint; STAThread>]
let main(args: string[]) =
AppBuilder
.Configure<App>()
.UsePlatformDetect()
.UseSkia()
.StartWithClassicDesktopLifetime(args) |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
Yes, your observation here is correct. The call to |
Beta Was this translation helpful? Give feedback.
-
Thanks for the confirmation. type Readable<'t> = | Readable of IReadable<'t>
module Readable =
let subscribe (ctx : IComponentContext) (Readable r) = ctx.usePassedRead r ... then let myComponent key (model : IReadable<Model>) dispatch =
Component.create (key,
fun ctx ->
//let model = ctx.usePassedRead model becomes let myComponent key (rmodel : Readable<Model>) dispatch =
Component.create (key,
fun ctx ->
let model = Readable.subscribe ctx rmodel ... and ContentControl.create [
Grid.row 0
ContentControl.content (
myComponent "c1" (Readable model) dispatch
)
] F# makes stuff like this quite painless :-) |
Beta Was this translation helpful? Give feedback.
-
My suggestion is to use shadowing. module MainView =
...
let myComponent key (model : IReadable<Model>) dispatch =
Component.create (key, fun ctx ->
(* shadows the passed model *)
let model = ctx.usePassedRead model
let flag = ctx.useState false
let value = model |> State.readMap (fun m -> m.Value)
...
) |
Beta Was this translation helpful? Give feedback.
Yes, your observation here is correct.
The call to
ctx.usePassed/ctx.usePassedRead
basically subscribes the component to changes of the passedIReadable
.