New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dropDown: parameter for selected option? #41

Closed
MattiasBuelens opened this Issue Dec 10, 2014 · 3 comments

Comments

Projects
None yet
4 participants
@MattiasBuelens

MattiasBuelens commented Dec 10, 2014

Graphics.Input.dropDown only takes a handler function and a list of options to render a drop-down list. However, this provides no way to set the drop-down's current selection. In particular, the selection can update a signal but a new signal cannot update the selection (and trigger a re-render). This is in contrast with other inputs: checkbox takes a Bool parameter for the current check state, and field takes a Content parameter for the current text and selection.

I'd like to see dropDown's signature being changed to something along the lines of:

dropDown : (a -> Signal.Message) -> List (String, a) -> a -> Element

where the third parameter is the selected option (which should also be present in the list of options). That way, one can for example map over the signal (obtained with Channel.subscribe) and provide the current value of the signal to use for the drop-down's selection. To use the same example as in the documentation:

type Sport = Football | Cricket | Snooker

sport : Signal.Channel (Maybe Sport)
sport = Signal.channel Nothing

sportDropDown : (Maybe Sport) -> Element
sportDropDown currentSport =
    dropDown (Signal.send sport)
      [ (""        , Nothing)
      , ("Football", Just Football)
      , ("Cricket" , Just Cricket)
      , ("Snooker" , Just Snooker)
      ] currentSport

main = map sportDropDown (Signal.subscribe sport)
@kfish

This comment has been minimized.

Show comment
Hide comment
@kfish

kfish Apr 30, 2015

I'd also like to see this supported. I made a local patch in mooltipass for this against 1.1.1, using the label String not the value a.

@evancz this is a breaking change, would you prefer a separate function?

diff --git a/elm-core/src/Graphics/Input.elm b/elm-core/src/Graphics/Input.elm
index 7d795c7..d3b222a 100644
--- a/elm-core/src/Graphics/Input.elm
+++ b/elm-core/src/Graphics/Input.elm
@@ -99,7 +99,7 @@ favorite British sport:
 If the user selects "Football" from the drop down menue, `Signal.subscribe sport`
 will update to `Just Football`.
 -}
-dropDown : (a -> Signal.Message) -> List (String, a) -> Element
+dropDown : (a -> Signal.Message) -> List (String, a) -> String -> Element
 dropDown =
   Native.Graphics.Input.dropDown

diff --git a/elm-core/src/Native/Graphics/Input.js b/elm-core/src/Native/Graphics/Input.js
index b2c7195..9aef2b7 100644
--- a/elm-core/src/Native/Graphics/Input.js
+++ b/elm-core/src/Native/Graphics/Input.js
@@ -36,6 +36,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             var name = values[i]._0;
             option.value = name;
             option.innerHTML = name;
+            if (name == model.selected) {option.selected = "true"} else { option.selected = null }
             drop.appendChild(option);
         }
         drop.addEventListener('change', function() {
@@ -59,6 +60,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             var name = values[i]._0;
             option.value = name;
             option.innerHTML = name;
+            if (name == newModel.selected) {option.selected = "true"} else { option.selected = null }
         }
         for (; i < kidsLength; ++i) {
             node.removeChild(node.lastChild);
@@ -68,12 +70,13 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             var name = values[i]._0;
             option.value = name;
             option.innerHTML = name;
+            if (name == newModel.selected) {option.selected = "true"} else { option.selected = null }
             node.appendChild(option);
         }
         return node;
     }

-    function dropDown(handler, values) {
+    function dropDown(handler, values, selected) {
         return A3(Element.newElement, 100, 24, {
             ctor: 'Custom',
             type: 'DropDown',
@@ -81,6 +84,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             update: updateDropDown,
             model: {
                 values: values,
+                selected: selected,
                 handler: handler
             }
         });
@@ -404,7 +408,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
         button: F2(button),
         customButton: F4(customButton),
         checkbox: F2(checkbox),
-        dropDown: F2(dropDown),
+        dropDown: F3(dropDown),
         field: mkField('text'),
         email: mkField('email'),
         password: mkField('password'),

kfish commented Apr 30, 2015

I'd also like to see this supported. I made a local patch in mooltipass for this against 1.1.1, using the label String not the value a.

@evancz this is a breaking change, would you prefer a separate function?

diff --git a/elm-core/src/Graphics/Input.elm b/elm-core/src/Graphics/Input.elm
index 7d795c7..d3b222a 100644
--- a/elm-core/src/Graphics/Input.elm
+++ b/elm-core/src/Graphics/Input.elm
@@ -99,7 +99,7 @@ favorite British sport:
 If the user selects "Football" from the drop down menue, `Signal.subscribe sport`
 will update to `Just Football`.
 -}
-dropDown : (a -> Signal.Message) -> List (String, a) -> Element
+dropDown : (a -> Signal.Message) -> List (String, a) -> String -> Element
 dropDown =
   Native.Graphics.Input.dropDown

diff --git a/elm-core/src/Native/Graphics/Input.js b/elm-core/src/Native/Graphics/Input.js
index b2c7195..9aef2b7 100644
--- a/elm-core/src/Native/Graphics/Input.js
+++ b/elm-core/src/Native/Graphics/Input.js
@@ -36,6 +36,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             var name = values[i]._0;
             option.value = name;
             option.innerHTML = name;
+            if (name == model.selected) {option.selected = "true"} else { option.selected = null }
             drop.appendChild(option);
         }
         drop.addEventListener('change', function() {
@@ -59,6 +60,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             var name = values[i]._0;
             option.value = name;
             option.innerHTML = name;
+            if (name == newModel.selected) {option.selected = "true"} else { option.selected = null }
         }
         for (; i < kidsLength; ++i) {
             node.removeChild(node.lastChild);
@@ -68,12 +70,13 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             var name = values[i]._0;
             option.value = name;
             option.innerHTML = name;
+            if (name == newModel.selected) {option.selected = "true"} else { option.selected = null }
             node.appendChild(option);
         }
         return node;
     }

-    function dropDown(handler, values) {
+    function dropDown(handler, values, selected) {
         return A3(Element.newElement, 100, 24, {
             ctor: 'Custom',
             type: 'DropDown',
@@ -81,6 +84,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
             update: updateDropDown,
             model: {
                 values: values,
+                selected: selected,
                 handler: handler
             }
         });
@@ -404,7 +408,7 @@ Elm.Native.Graphics.Input.make = function(localRuntime) {
         button: F2(button),
         customButton: F4(customButton),
         checkbox: F2(checkbox),
-        dropDown: F2(dropDown),
+        dropDown: F3(dropDown),
         field: mkField('text'),
         email: mkField('email'),
         password: mkField('password'),
@wmakley

This comment has been minimized.

Show comment
Hide comment
@wmakley

wmakley Feb 23, 2016

I have discovered a related issue: I have a list of elements, where each element has a <select> with some options. If I change the value of the first <select>, then remove it from the DOM, elm sets the second <select> to the same value. Seems to be re-using the node or something.

wmakley commented Feb 23, 2016

I have discovered a related issue: I have a list of elements, where each element has a <select> with some options. If I change the value of the first <select>, then remove it from the DOM, elm sets the second <select> to the same value. Seems to be re-using the node or something.

@evancz

This comment has been minimized.

Show comment
Hide comment
@evancz

evancz May 11, 2016

Member

Sorry this did not get attention til now! The Graphics.* modules now live in evancz/elm-graphics so I am trying to get stuff migrated over there. The input elements did not make the leap though, so the fix is to use HTML and SVG for this sort of stuff.

Member

evancz commented May 11, 2016

Sorry this did not get attention til now! The Graphics.* modules now live in evancz/elm-graphics so I am trying to get stuff migrated over there. The input elements did not make the leap though, so the fix is to use HTML and SVG for this sort of stuff.

@evancz evancz closed this May 11, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment