From 846629a9656e0c7280a59ac9da2a974016ccbb35 Mon Sep 17 00:00:00 2001 From: Sergej Dick Date: Wed, 23 Jan 2019 08:50:20 +0100 Subject: [PATCH 01/13] added a documentation for webrequest with fsharp.data --- docs/update.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/update.md b/docs/update.md index e41473f95..4102edeba 100644 --- a/docs/update.md +++ b/docs/update.md @@ -170,6 +170,53 @@ let update msg model = | PictureTaken -> ... ``` +Webrequests in a Command +---- +Sometimes it is needed to make some web requests. Which tool you use here does not matter. For example you could use FSharp.Data to make HttpRequests. +These are the steps that you have to do, to make it work: +1. Create a case in the message type for a successful and failure webrequests +```fsharp +type Msg = + | LoginClicked + | LoginSuccess + | AuthError +``` +2. Implement the Command and return the correct message +```fsharp +let authUser (username: string) (password: string) = + async { + do! Async.SwitchToThreadPool() + // make your http call + // FSharp.Data.HTTPUtil is used here + let! response = + Http.AsyncRequest(url=URL, + body = TextRequest """ {"username": "test", "password": "testpassword"} """, + httpMethod="POST", + silentHttpErrors = true) + let r = match response.StatusCode with + | 200 -> LoginSuccess + | _ -> AuthError + + return r; + } |> Cmd.ofAsyncMsg +``` +3. Call the Command from update e.g. when a button is clicked +```fsharp +let update msg model = + | LoginClicked -> + {model with IsRunning=true}, authUser model.Username model.Password // Call the Command + | LoginSuccess -> + {model with IsLoggedIn = true; IsRunning=false}, Cmd.none + | AuthError -> + {model with IsLoggedIn = false; IsRunning=false}, Cmd.none +``` +4. Create your view as you need +```fsharp +match model.IsLoggedIn with + | true -> LoggedInSuccesful + | false -> LoginView +``` + Platform-specific dispatch ----- From ceb07b30df82e7d020d6ca067dd387ae3fd39778 Mon Sep 17 00:00:00 2001 From: SergejDK Date: Wed, 23 Jan 2019 18:30:58 +0100 Subject: [PATCH 02/13] code formatting with fantomas --- docs/update.md | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/docs/update.md b/docs/update.md index 4102edeba..21b58a423 100644 --- a/docs/update.md +++ b/docs/update.md @@ -176,45 +176,46 @@ Sometimes it is needed to make some web requests. Which tool you use here does n These are the steps that you have to do, to make it work: 1. Create a case in the message type for a successful and failure webrequests ```fsharp -type Msg = +type Msg = | LoginClicked | LoginSuccess | AuthError ``` 2. Implement the Command and return the correct message ```fsharp -let authUser (username: string) (password: string) = +let authUser (username : string) (password : string) = async { do! Async.SwitchToThreadPool() // make your http call // FSharp.Data.HTTPUtil is used here - let! response = - Http.AsyncRequest(url=URL, - body = TextRequest """ {"username": "test", "password": "testpassword"} """, - httpMethod="POST", - silentHttpErrors = true) - let r = match response.StatusCode with + let! response = Http.AsyncRequest + (url = URL, body = TextRequest """ {"username": "test", "password": "testpassword"} """, + httpMethod = "POST", silentHttpErrors = true) + let r = + match response.StatusCode with | 200 -> LoginSuccess | _ -> AuthError - - return r; - } |> Cmd.ofAsyncMsg + return r + } + |> Cmd.ofAsyncMsg ``` 3. Call the Command from update e.g. when a button is clicked ```fsharp let update msg model = - | LoginClicked -> - {model with IsRunning=true}, authUser model.Username model.Password // Call the Command + match msg with + | LoginClicked -> { model with IsRunning = true }, authUser model.Username model.Password // Call the Command | LoginSuccess -> - {model with IsLoggedIn = true; IsRunning=false}, Cmd.none + { model with IsLoggedIn = true + IsRunning = false }, Cmd.none | AuthError -> - {model with IsLoggedIn = false; IsRunning=false}, Cmd.none + { model with IsLoggedIn = false + IsRunning = false }, Cmd.none ``` 4. Create your view as you need ```fsharp match model.IsLoggedIn with - | true -> LoggedInSuccesful - | false -> LoginView +| true -> LoggedInSuccesful +| false -> LoginView ``` Platform-specific dispatch From c964b50c7aefaa962356107fcea2588470c7cf94 Mon Sep 17 00:00:00 2001 From: SergejDK Date: Wed, 23 Jan 2019 23:50:54 +0100 Subject: [PATCH 03/13] added sample --- .../AllControls/AllControls/AllControls.fs | 144 ++++++++++++------ .../AllControls/AllControls.fsproj | 1 + .../Droid/AllControls.Droid.fsproj | 8 +- 3 files changed, 102 insertions(+), 51 deletions(-) diff --git a/samples/AllControls/AllControls/AllControls.fs b/samples/AllControls/AllControls/AllControls.fs index d6bf4c3a7..a06b472b0 100644 --- a/samples/AllControls/AllControls/AllControls.fs +++ b/samples/AllControls/AllControls/AllControls.fs @@ -5,6 +5,7 @@ open System open Fabulous.Core open Fabulous.DynamicViews open Xamarin.Forms +open FSharp.Data type RootPageKind = | Choice of bool @@ -16,6 +17,7 @@ type RootPageKind = | MasterDetail | InfiniteScrollList | Animations + | WebCall type Model = { RootPageKind: RootPageKind @@ -47,6 +49,10 @@ type Model = SearchTerm: string CarouselCurrentPageIndex: int Tabbed1CurrentPageIndex: int + // For WebCall page demo + IsRunning: bool + ReceivedData: bool + WebCallData: string option } type Msg = @@ -95,6 +101,10 @@ type Msg = | SetCarouselCurrentPage of int | SetTabbed1CurrentPage of int | ReceivedLowMemoryWarning + // For WebCall page demo + | ReceivedDataSuccess of string option + | ReceivedDataFailure of string option + | ReceiveData [] module MyExtension = @@ -164,86 +174,101 @@ module App = InfiniteScrollMaxRequested = 10 SearchTerm = "nothing!" CarouselCurrentPageIndex = 0 - Tabbed1CurrentPageIndex = 0 } + Tabbed1CurrentPageIndex = 0 + IsRunning = false + ReceivedData = false + WebCallData = None }, Cmd.none + + let getWebData = + async { + do! Async.SwitchToThreadPool() + let! response = + Http.AsyncRequest(url="https://api.myjson.com/bins/1ecasc", httpMethod="GET", silentHttpErrors=true) + let r = + match response.StatusCode with + | 200 -> Msg.ReceivedDataSuccess (Some (response.Body |> string)) + | _ -> Msg.ReceivedDataFailure (Some "Failed to get data") + return r + } |> Cmd.ofAsyncMsg let animatedLabelRef = ViewRef