@@ -289,7 +289,7 @@ defmodule Phoenix.HTML.Form do
289289 an atom, string or integer to be used as the option value
290290 * simple atom, string or integer - which will be used as both label and value
291291 for the generated select
292-
292+
293293 ## Option groups
294294
295295 If `options` is map or keyword list where the first element is a string,
@@ -320,6 +320,12 @@ defmodule Phoenix.HTML.Form do
320320 #=> <option>France</option>
321321 #=> </optgroup>
322322
323+ Custom option tags:
324+
325+ options_for_select(["Admin": "admin", "User": "user"], nil, tag: "opt")
326+ #=> <opt value="admin">Admin</opt>
327+ #=> <opt value="user">User</opt>
328+
323329 Horizontal separators can be added:
324330
325331 options_for_select(["Admin", "User", :hr, "New"], nil)
@@ -336,21 +342,22 @@ defmodule Phoenix.HTML.Form do
336342
337343
338344 """
339- def options_for_select ( options , selected_values ) do
345+ def options_for_select ( options , selected_values , extra \\ [ ] ) do
340346 { :safe ,
341347 escaped_options_for_select (
342348 options ,
343- selected_values |> List . wrap ( ) |> Enum . map ( & html_escape / 1 )
349+ selected_values |> List . wrap ( ) |> Enum . map ( & html_escape / 1 ) ,
350+ extra
344351 ) }
345352 end
346353
347- defp escaped_options_for_select ( options , selected_values ) do
354+ defp escaped_options_for_select ( options , selected_values , extra ) do
348355 Enum . reduce ( options , [ ] , fn
349356 { :hr , nil } , acc ->
350357 [ acc | hr_tag ( ) ]
351358
352359 { option_key , option_value } , acc ->
353- [ acc | option ( option_key , option_value , [ ] , selected_values ) ]
360+ [ acc | option ( option_key , option_value , extra , selected_values ) ]
354361
355362 options , acc when is_list ( options ) ->
356363 { option_key , options } =
@@ -373,27 +380,28 @@ defmodule Phoenix.HTML.Form do
373380 { value , options }
374381 end
375382
376- [ acc | option ( option_key , option_value , options , selected_values ) ]
383+ [ acc | option ( option_key , option_value , extra ++ options , selected_values ) ]
377384
378385 :hr , acc ->
379386 [ acc | hr_tag ( ) ]
380387
381388 option , acc ->
382- [ acc | option ( option , option , [ ] , selected_values ) ]
389+ [ acc | option ( option , option , extra , selected_values ) ]
383390 end )
384391 end
385392
386- defp option ( group_label , group_values , [ ] , value )
393+ defp option ( group_label , group_values , extra , value )
387394 when is_list ( group_values ) or is_map ( group_values ) do
388- section_options = escaped_options_for_select ( group_values , value )
395+ section_options = escaped_options_for_select ( group_values , value , extra )
389396 option_tag ( "optgroup" , [ label: group_label ] , { :safe , section_options } )
390397 end
391398
392399 defp option ( option_key , option_value , extra , value ) do
393400 option_key = html_escape ( option_key )
394401 option_value = html_escape ( option_value )
395402 attrs = extra ++ [ selected: option_value in value , value: option_value ]
396- option_tag ( "option" , attrs , option_key )
403+ { tag , attrs } = Keyword . pop ( attrs , :tag , "option" )
404+ option_tag ( tag , attrs , option_key )
397405 end
398406
399407 defp option_tag ( name , attrs , { :safe , body } ) when is_binary ( name ) and is_list ( attrs ) do
0 commit comments