It would be highly useful if there was a way to prevent view, subscription,
or update from being called while also allowing for module transformation
for TEA/following modules, which could all be handled via adding a single
callback (described below) to Program (or a new version there-of). It
would require a simple change to the core javascript native code (linked
below). Just having Html.lazy on the top view itself is insufficient as it
does not handle being able to prevent update calls (say if the model does
not change and no command is raised, useful for view update, a rare case
and could be ignored in general), being able to prevent or filter
subscriptions (highly important in many cases, this would allow for ignore
certain subscription messages, say you are handling input and do not want
to listen to certain keys or only want to listen to certain keys then this
would allow you to handle both filtering it as well as translating the the
filtered data into a new message if wanted all in one step), as well as
also preventing view updates on a variety of model updates (ways that lazy
fails badly in is if you are receiving a stream of messages from a server,
each one is causing a view update, when they are incoming as a singular
stream and you know when it stops and can turn back 'on' rendering at that
point, thus completely ignore the view updates for the given message stream
Message and leave it on for everything else). You could potentially nest
lazy's only matching on specific criteria and a model variable to define
whether it is on or not, but then you have to make sure you always turn it
on on message types that handle views and turn it off only for your
specific one, when that really should both be reversed in structure and
should have no state variable. Such a callback could also handle module
transformation for TEA styled handling.
Thus for the new callback I propose is something like this, called `blah`
for now since I am bad with naming and do not want to pre-dispose an idea
of how it should work based on the name:
```elm
module main exposing (..)
main : Program ProgramFlagsmain =
App.programWithFlags
{ init = init
, blah = blah
, view = view
, update = update
, subscriptions = subscriptions
}
-- Snip other callback code as they are unchanged
blah : Msg -> ( Msg, States )blah msg =
case msg of
MyMessageThree _ -> ( msg, States.batch [ States.cancelView,
States.cancelSubscriptions ) -- Just preventing certain callbacks
MyMessageNine arg0 _ -> ( MyMessageThree arg0, States.all ) -- -- Just
converting a message to another
MyRedrawMessage -> ( msg, States.onlyView ) -- Just redraw the view, unsure
if necessary but it is here for completion.
MyMessageTwelve _ -> ( msg, States.onlyUpdate ) -- Just handle an update,
subscriptions and view are not called
OnKeyPress 13 -> ( msg, States.none ) -- Cancel every callback when
OnKeyPress's value is 13, else it will fall back to the default lower of _ that
passes through everything unchanged
OnKeyPress 119 -> ( MoveUp, States.all) -- Convert this specific OnKeyPress
into a MoveUp message instead, the OnKeyPress vanishes
MaterialMessage msg -> Material.blah .mdl (\model newMdl -> { model |
mdl=newMdl } ) msg
_ -> ( msg, States.noChanges )
-- Material.blah could be implemented likemodule Material
blah : ( model -> Material.Model ) -> ( model -> Material.Model -> model ) ->
Material.Msg -> ( Msg, States )blah getModel putModel msg =
( msg
, States.delegate
{ getModel=getModel
, putModel=putModel
, update=Material.update
, subscriptions=Material.subscriptions
}
)
```
As you can see it allows but is not restricted to:
- Message translation
- Callback cancellation
- Message filtering
- Message filtering and translation
- TEA models direct update/subscriptions conversion (Just like how you
can do `.mdl model` to get `model.mdl`, I wish there were a way to do
something like `put .mdl model something` and it does `{ model | mdl =
something }`, it would make that last second callback more simple)
- <salesman-voice>And more!
This solves a variety of issues in but not restricted to:
- Simplifying the update to only handle what is actually important
- Calling view at all only when it is needed (letting you not call it on
hot-path messages for example, like when getting a thousand messages to
fill in something but you don't want to render it until the stream is
complete)
- TEA style inclusion of other modules in a central-include point
without needing to pepper crap like this all over your update and more:
```elm
Helpers helpersMsg ->
let
( helpersModel, helpersCmd ) =
helpers_update Helpers helpersMsg model.helpers
in
( { model | helpers = helpersModel }
, helpersCmd
)
```
This is my prior post about this:
I do say that I wish there were some way to make some 'update' call as
no-view and/or no-subscription re-call needed. Like instead of returning
`( model, Cmd.none )` we could do `( model, Cmd.cancelView )` or `( model,
Cmd.cancelSubscription )` or both via `Cmd.batch`, or perhaps as a
three-argument tuple that defaults to `( model, Cmd.none, StateChanges.none
)` or so, which would default to calling everything. I have a lot of
update messages that are handled that do not change the view and/or
subscriptions and it would be nice to prevent calling those somehow. Hmm,
actually a backward compatible change would be to add a new Program
callback, in addition to the usual `init`, `update`, `subscriptions`, and
`view`, add another one that I will call just `blah` for now, optional in
the Program or so, but have it be like:
```
blah : Msg -> ( Msg, States )
blah msg ->
case msg of
MyMessageThree _ -> ( msg, States.batch [ States.cancelView,
States.cancelSubscriptions )
MyMessageNine arg0 _ -> ( MyMessageThree arg0, States.noChanges ) -- or
`States.none`?
MyRedrawMessage -> ( msg, States.cancelView )
MyMessageTwelve _ -> ( msg, States.onlyUpdate )
_ -> ( msg, States.noChanges )
```
And it would be called after `init` and before every call of `update`. It
would allow an easy way to translate one message type into another (maybe
even a way to decorate it more so it can get passed to another modules
update/subscription, this would be a **great** hooking location for
modules), as well as a way to specify what states should be updated for a
given message, a default no-op function could be supplied via
`States.defaultHandle` or so that you could pass to the program so people
do not have to override it in the easy cases.
Hmm, an idea for a module handler, one of the states could be something
like:
```elm
MaterialMessage msg -> ( msg, States.delegate { update=Material.update,
subscriptions=Material.subscriptions } )
```
Which of course the other module could simplify via a helper to:
```elm
MaterialMessage msg -> Material.blah msg
```
Looking at
https://github.com/elm-lang/core/blob/4.0.4/src/Native/Platform.js shows
that it would be easy to add that functionality to core.
So ideas about this style, issues, etc...?
--
You received this message because you are subscribed to the Google Groups "Elm
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.