This is a simple example of how is possible to implement a third party Carousel plugin in a Single Page Application (SPA) made in Elm.
The plugin is the excellent Flickity (https://flickity.metafizzy.co/), one of the simplest and smoother Carousel implementation. It works both with jQuery and without jQuery. In this example I am implementing it without jQuery.
First I create the html skeleton of the carousel:
div []
[ h1 [] [ text "Carousel" ]
, div [ class "carousel" ]
[ div [ class "carousel-cell" ]
[]
, div [ class "carousel-cell" ]
[]
, div [ class "carousel-cell" ]
[]
, div [ class "carousel-cell" ]
[]
, div [ class "carousel-cell" ]
[]
]
]
Inside you can have images, text or anything else. For this example I use these empty cells that will be filled with some Css, as per this example https://codepen.io/desandro/pen/myXdej
Because the site is implemented as SPA i need to initialise the plugin every time the page that contains the carousel is active. To do this I create a port to communicate to Javascript.
port urlChange : String -> Cmd msg
Being a SPA, the main function send the UrlChange message every time the url change
main : Program Never Model Msg
main =
Navigation.program UrlChange
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
In the update section, every time the UrlChange message arrive, I send the location.hash
, that contain the part after the # in the url, to Javascript through the urlChange port
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UrlChange location ->
( { model | history = location :: model.history }
, (urlChange location.hash)
)
In index.html I receive the hash and, if it is the same as #carousel
, that is the page that contain the carousel, I activate it.
var app = Elm.Main.embed(document.getElementById('app'));
app.ports.urlChange.subscribe(function(page) {
if (page === "#carousel") {
window.requestAnimationFrame(function () {
var element = document.getElementsByClassName("carousel")[0];
var flkty = new Flickity(element, { "wrapAround": true });
});
}
});
Note that I use window.requestAnimationFrame
. This is needed to be sure that the element is already created by Elm, before I try to initialise the plugin. Elm renders the view using requestAnimationFrame so using requestAnimationFrame from Javascript means that we enter in the queue and our callback will be executed after Elm render.
You can find the code here: https://github.com/lucamug/elm-carousel and a live demo here: https://lucamug.github.io/elm-carousel/