Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First draft for component support #49

Merged
merged 13 commits into from
Nov 22, 2023
Merged

First draft for component support #49

merged 13 commits into from
Nov 22, 2023

Conversation

TimLariviere
Copy link
Member

@TimLariviere TimLariviere commented Nov 20, 2023

Details here: https://github.com/fabulous-dev/FabPlaygroundCE/blob/main/FabPlaygroundCE/Playground.fs

Simple stateful component

module Counter =
    let body =
        view {
            let! count = state 0
            
            VStack() {
                Label($"Count is {count.Current}")
                    .centerHorizontal()
                
                Button'("Increment", fun () -> count.Set(count.Current + 1))
                Button'("Decrement", fun () -> count.Set(count.Current - 1))
            }
        }
comp.mov

Parent-child communication

module ParentChild =
    let child count =
        view {
            let! multiplier = state 1
            let countMultiplied = count * multiplier.Current
            
            VStack() {
                Label($"Count * {multiplier.Current} = {countMultiplied}")
                    .centerHorizontal()
                    
                Button'("Increment Multiplier", fun () -> multiplier.Set(multiplier.Current + 1))
                Button'("Decrement Multiplier", fun () -> multiplier.Set(multiplier.Current - 1))
            }
        }
        
    let parent =
        view {
            let! count = state 0
            
            VStack() {
                Label($"Count is {count.Current}")
                    .centerHorizontal()
                
                Button'("Increment Count", fun () -> count.Set(count.Current + 1))
                Button'("Decrement Count", fun () -> count.Set(count.Current - 1))
                    
                Component(child count.Current)
            }
        }
compchild.mov

samples/HelloWorld/App.fs Outdated Show resolved Hide resolved
@TimLariviere
Copy link
Member Author

Changed the ergonomics to be more in line with the current DSL:

type Fabulous.Maui.View with
    static member inline SimpleComponent() =
        Component() {
            Label("Hello Component")
                .centerHorizontal()
        }

    static member inline Counter() =
        Component() {
            let! count = state 0
            
            VStack() {
                Label($"Count is {count.Current}")
                    .centerHorizontal()
                
                Button'("Increment", fun () -> count.Set(count.Current + 1))
                Button'("Decrement", fun () -> count.Set(count.Current - 1))
            }
        }
        
    static member inline ParentChild_Child(count: int) =
        Component() {
            let! multiplier = state 1
            let countMultiplied = count * multiplier.Current
            
            VStack() {
                Label($"Count * {multiplier.Current} = {countMultiplied}")
                    .centerHorizontal()
                    
                Button'("Increment Multiplier", fun () -> multiplier.Set(multiplier.Current + 1))
                Button'("Decrement Multiplier", fun () -> multiplier.Set(multiplier.Current - 1))
            }
        }
    
    static member inline ParentChild_Parent() =
        Component() {
            let! count = state 0
            
            VStack() {
                Label($"Count is {count.Current}")
                    .centerHorizontal()
                
                Button'("Increment Count", fun () -> count.Set(count.Current + 1))
                Button'("Decrement Count", fun () -> count.Set(count.Current - 1))
                
                View.ParentChild_Child(count.Current)
            }
        }
        
    static member inline Child(count: BindingRequest<'T>) =
        Component() {
            let! boundCount = count
            
            VStack() {
                Label($"Child.Count is {boundCount.Current}")
                    .centerHorizontal()
                
                Button'("Increment", fun () -> boundCount.Set(boundCount.Current + 1))
                Button'("Decrement", fun () -> boundCount.Set(boundCount.Current - 1))
            }
        }
    
    static member inline BindingBetweenParentAndChild() =
        Component() {
            let! count = state 0
            
            VStack() {
                Label($"Parent.Count is {count.Current}")
                    .centerHorizontal()
                    
                Button'("Increment", fun () -> count.Set(count.Current + 1))
                Button'("Decrement", fun () -> count.Set(count.Current - 1))
                
                View.Child(ofState count)
            }
        }
    
    static member inline SharedContextBetweenComponents() =
        Component() {
            let sharedContext = ComponentContext()
            
            VStack() {
                View.Counter()
                    .withContext(sharedContext)
                    
                View.Counter()
                    .withContext(sharedContext)
            }
        }

@TimLariviere
Copy link
Member Author

TimLariviere commented Nov 20, 2023

@edgarfgp btw I managed to remove the need for the intermediate Border control. Component acts as a proxy widget.
Might require some more tinkering but it's working :)

@TimLariviere TimLariviere marked this pull request as ready for review November 22, 2023 10:17
@TimLariviere TimLariviere added this pull request to the merge queue Nov 22, 2023
Merged via the queue into main with commit c2cf71b Nov 22, 2023
1 check passed
@TimLariviere TimLariviere deleted the components branch November 22, 2023 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants