7
\$\begingroup\$

I have made my first app in Elm, a lookup of Github users.

You type the name of the user into the search bar and the user's username and profile image - which has an anchor linked to their profile - appears below.

Here is my code:

module Main exposing (..)

import Html exposing (..)
import Html.App as App
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)


main =
    App.beginnerProgram { model = model, view = view, update = update }



-- MODEL


type alias Model =
    { username : String }


model : Model
model =
    { username = "" }



-- UPDATE


type Msg
    = Change String


update : Msg -> Model -> Model
update msg model =
    case msg of
        Change newUsername ->
            { model | username = newUsername }



-- VIEW


view : Model -> Html Msg
view model =
    div
        [ style
            [ ( "display", "flex" )
            , ( "justify-content", "center" )
            , ( "align-items", "center" )
            , ( "flex-direction", "column" )
            ]
        ]
        [ input
            [ placeholder "Search for a Github username"
            , onInput Change
            , style
                [ ( "font-size", "30px" )
                , ( "padding", "10px" )
                , ( "width", "600px" )
                ]
            ]
            []
        , div []
            [ h5 [] [ text model.username ]
            ]
        , a [ href ("https://github.com/" ++ model.username) ]
            [ img
                [ src ("https://github.com/" ++ model.username ++ ".png")
                , style [ ( "max-width", "200px" ) ]
                ]
                []
            ]
        ]

Here is a demo of it in action: https://alanbuchanan.github.io/GithubUserLookup.html

I used elm-format to format the code, and based the architecture from the documentation.

  1. The code returned in the view is messy. How can I tidy my code so that the styles applied do not take up space inside the main div of the view, perhaps instead within a variable beforehand?
  2. How else can I optimise this code?
\$\endgroup\$
3
\$\begingroup\$

From the functional point of view what you're doing is a bit odd as you always create a link and try to load an image, even for non-existing users.

You should better query the GitHub API and change your model to something like:

type alias Model =
  { username : String -- this is the string typed in the input box
  , user : Maybe User -- this is the parsed result from the API call
  }

then, you can create a viewUser : User -> Html Msg function to show the username and the image. Note that your model has a Maybe User so you'll have to pattern match in view and either call viewUser (if you have something to show) or display some text explaining that the current query doesn't match with a valid GitHub user.

Note that invoking the API and getting a result is a bit more convoluted than it is in JavaScript. You need to do an HTTP request and create a Json decoder.

Said that, let's go back to the code you wrote. I agree with the comments in the other answer and I'd like to add a few things:

  • comments like -- MODEL are not particularly useful. I'd get rid of them;
  • Change is not really self-explanatory. What does it change? I'd rename it to QueryChanged or something similar.
  • as I mentioned already, view could be split in smaller functions each one taking care of visualising/styling a single component.

In your question you asked about how to optimise your code. Are you looking for performance improvement? Why?

\$\endgroup\$
2
\$\begingroup\$

I would split out the each of the style definitions into a function of their own. For instance:

-- VIEW
mainDivStyles : Html.Attribute Msg
mainDivStyles =
    style
        [ ( "display", "flex" )
        , ( "justify-content", "center" )
        , ( "align-items", "center" )
        , ( "flex-direction", "column" )
        ]

formInputStyles : Html.Attribute Msg
formInputStyles = 
    style
        [ ( "font-size", "30px" )
        , ( "padding", "10px" )
        , ( "width", "600px" )
        ]

view : Model -> Html Msg
view model =
    div
        [ mainDivStyles ]

        [ input
            [ placeholder "Search for a Github username"
            , onInput Change
            , formInputStyles
            ]
            []

This cleans up the vie code considerably and makes it easier to read.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.