How to call http request when the page get called?

Hi all
I have a page, that has the following code snippet:

module Account.View exposing (Msg(..), show)

import API.Keycloak as Keycloak exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Keyed as Keyed
import Http
import Json.Decode as Decode



---- UPDATE ----


type alias Currs =
    Result Http.Error String


type alias Model =
    { currs : Currs
    }


type Msg
    = GetCurrs
    | SaveCurrs Currs


init : Msg
init =
    GetCurrs


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GetCurrs ->
            ( model, getCurrs )

        SaveCurrs newCurrs ->
            ( { model | currs = newCurrs }, Cmd.none )


view : Model -> Html Msg
view model =
    case model.currs of
        Ok _ ->
            p [] [ text "Got Currs" ]

        Err _ ->
            p [] [ text "Failed" ]


getCurrs : Cmd Msg
getCurrs =
    Http.send SaveCurrs (Http.getString "/coins")


show : Keycloak.Struct -> Html Msg
show token =
    p [] [ text token.subject ]

And it will be called from the main, if the url is matched:

matchedRoute : Keycloak.Token -> Route.Route -> Html Msg
matchedRoute token path =
    case token of
        Ok struct ->
            case path of
                Route.Home ->
                    Home.content

                Route.Account ->
                    Html.map (\_ -> Transformer) (Account.show struct) --> Will be called here

        Err error ->
            NotAuthorized.show 

I am trying the archive, if Account.show struct get called, then in the show function it should carry out reqCurrencies and the view should show the received result.

Thanks

If I understand correctly, you are trying to do a request when the user navigates to the account route. Is that right? From looking at your code I couldn’t tell where matchedRoute is called.

A pattern I use is to

  • Trigger a message when the location changes e.g. OnLocationChange Url

  • Parse the Url and store the route in the model

  • Then call a function like initCurrentPage

  • This initCurrentPage function will make the request if necessary, something like:

      initCurrentPage model currentCommands =
          case model.route of
               Route.Home ->
                   (model, currentCommands)
              Route.Account ->
                  (model, Cmd.batch [currentCommands, reqCurrencies] )

First of all, thanks for your response.
I created a Main.elm that has the following content

module Main exposing (Model, Msg(..), init, main, update, view)

import API.Keycloak as Keycloak exposing (..)
import Account.View as Account
import Browser
import Browser.Navigation as Nav
import Home.View as Home
import Html exposing (..)
import Html.Attributes exposing (..)
import Json.Decode as Decode
import NotAuthorized.View as NotAuthorized
import NotFound.View as NotFound
import Route
import Url
import Url.Parser exposing ((</>), Parser, int, map, oneOf, parse, s, string)



---- MODEL ----


type alias Model =
    { key : Nav.Key
    , url : Url.Url
    , auth : Keycloak.Token
    }


init : Decode.Value -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
    ( Model key url (Keycloak.validate flags), Cmd.none )



---- UPDATE ----


type Msg
    = LinkClicked Browser.UrlRequest
    | UrlChanged Url.Url
    | Transformer


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        LinkClicked urlRequest ->
            case urlRequest of
                Browser.Internal url ->
                    ( model, Nav.pushUrl model.key (Url.toString url) )

                Browser.External href ->
                    ( model, Nav.load href )

        UrlChanged url ->
            ( { model | url = url }
            , Cmd.none
            )

        Transformer ->
            ( model, Cmd.none )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions _ =
    Sub.none



---- VIEW ----


info : Html Msg
info =
    header [] [ text "Header" ]


createLink : String -> String -> Html Msg
createLink aPath aText =
    a [ href ("/" ++ aPath) ] [ text aText ]


navigation : Html Msg
navigation =
    ul []
        [ li [] [ createLink "" "home" ]
        , li [] [ createLink "account" "account" ]
        ]


content : Model -> Html Msg
content model =
    main_ []
        [ case parse Route.parser model.url of
            Just path ->
                matchedRoute model.auth path

            Nothing ->
                NotFound.content
        ]


matchedRoute : Keycloak.Token -> Route.Route -> Html Msg
matchedRoute token path =
    case token of
        Ok struct ->
            case path of
                Route.Home ->
                    Home.content

                Route.Account ->
                    Html.map (\_ -> Transformer) (Account.show struct)

        Err error ->
            NotAuthorized.show


body : Model -> List (Html Msg)
body model =
    [ info
    , navigation
    , content model
    ]


view : Model -> Browser.Document Msg
view model =
    { title = "Cockpit"
    , body = body model
    }



---- PROGRAM ----


main : Program Decode.Value Model Msg
main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        , onUrlChange = UrlChanged
        , onUrlRequest = LinkClicked
        }

and another file called Account.View with following content:

module Account.View exposing (Msg(..), show)

import API.Keycloak as Keycloak exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Keyed as Keyed
import Http
import Json.Decode as Decode



---- UPDATE ----


type alias Currs =
    Result Http.Error String


type alias Model =
    { currs : Currs
    , token : Keycloak.Token
    }


type Msg
    = GetCurrs
    | SaveCurrs Currs
    | SaveKc Keycloak.Token


init : Msg
init =
    GetCurrs


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GetCurrs ->
            ( model, getCurrs )

        SaveCurrs newCurrs ->
            ( { model | currs = newCurrs }, Cmd.none )

        SaveKc newToken ->
            ( { model | token = newToken }, Cmd.none )


view : Model -> Html Msg
view model =
    case model.currs of
        Ok _ ->
            p [] [ text "Got Currs" ]

        Err _ ->
            p [] [ text "Failed" ]


getCurrs : Cmd Msg
getCurrs =
    Http.send SaveCurrs (Http.getString "/coins")


show : Keycloak.Struct -> Html Msg
show token =
    p [] [ text token.subject ]

what am I trying the archive is, to build SPA page.
Looking at the following function in the Main.elm:

matchedRoute : Keycloak.Token -> Route.Route -> Html Msg
matchedRoute token path =
    case token of
        Ok struct ->
            case path of
                Route.Home ->
                    Home.content

                Route.Account ->
                    Html.map (\_ -> Transformer) (Account.show struct)

When the route matches, then the show function in the Accout.View get called (edited)
In the show function, I would like to call getCurrs and then it should update the view.
I know, how to do it in the Main.elm file, but I would like to do in Accout.View file. (edited)
Or maybe I followed the wrong approach

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.