Reduce API Surface of Built-In Components
Summary
In order to reduce the API surface of the built-in <LinkTo>
, <Input>
and
<Textarea>
components, we propose to deprecate all named arguments on these
components except the following:
<LinkTo>
@route
@model
@models
@query
@replace
@disabled
@current-when
@activeClass
@loadingClass
@disabledClass
<Input>
@type
@value
@checked
@insert-newline
@enter
@escape-press
<Textarea>
@value
@insert-newline
@enter
@escape-press
Motivation
This is a follow-up to RFC #671 and shares the same high-level motivations and historical context.
Detailed design
The following named arguments should be explicitly documented as public:
<LinkTo>
@route
@model
@models
@query
@replace
@disabled
@current-when
@activeClass
@loadingClass
@disabledClass
<Input>
@type
@value
@checked
@insert-newline
@enter
@escape-press
<Textarea>
@value
@insert-newline
@enter
@escape-press
The arguments not enumerated above are either no longer necessary, recommended or accidentally exposed private implementation details.
No Longer Necessary
HTML Attributes
The built-in components historically accepted a varierty of named arguments for applying certain HTML attributes to the component's HTML element. This includes the following (may not be a complete list):
<LinkTo>
@id
@elementId
(alias for@id
)@ariaRole
(maps to therole
HTML attribute)@class
@classNames
(deprecated, expands into theclass
HTML atttribute)@classNameBindings
(deprecated, expands to theclass
HTML atttribute)@isVisible
(deprecated, expands to thedisplay: none
inline style)@rel
@tabindex
@target
@title
<Input>
@id
@elementId
(alias for@id
)@ariaRole
(maps to therole
HTML attribute)@class
@classNames
(deprecated, expands into theclass
HTML atttribute)@classNameBindings
(deprecated, expands to theclass
HTML atttribute)@isVisible
(deprecated, expands to thedisplay: none
inline style)@accept
@autocapitalize
@autocomplete
@autocorrect
@autofocus
@autosave
@dir
@disabled
@form
@formaction
@formenctype
@formmethod
@formnovalidate
@formtarget
@height
@indeterminate
@inputmode
@lang
@list
@max
@maxlength
@min
@minlength
@multiple
@name
@pattern
@placeholder
@readonly
@required
@selectionDirection
@size
@spellcheck
@step
@tabindex
@title
@width
<Textarea>
@id
@elementId
(alias for@id
)@ariaRole
(maps to therole
HTML attribute)@class
@classNames
(deprecated, expands into theclass
HTML atttribute)@classNameBindings
(deprecated, expands to theclass
HTML atttribute)@isVisible
(deprecated, expands to thedisplay: none
inline style)@autocapitalize
@autocomplete
@autocorrect
@autofocus
@cols
@dir
@disabled
@form
@lang
@maxlength
@minlength
@name
@placeholder
@readonly
@required
@rows
@selectionDirection
@selectionEnd
@selectionStart
@spellcheck
@tabindex
@title
@wrap
These arguments are no longer necessary – with angle bracket invocations, HTML attributes can be passed directly. An invocation passing one or more of these named arguments shall trigger a deprecation warning similar to this:
~~~~~~~~~~~~~~~~~~~~~~~
or
{{input placeholder="Ember.js"}}
~~~~~~~~~~~~~~~~~~~~~~
Passing the `@placeholder` argument to is deprecated. Instead, please
pass the attribute directly, i.e. `` instead of
`` or `{{input placeholder=...}}`.
A notable exception when passing an argument named @href
to the <LinkTo>
component. This was never intentionally supported and will trigger an error
instead of a deprecation warning.
DOM Events
The built-in components historically accepted a varierty of named arguments for listening to certain DOM events on the component's HTML element. This includes the following (may not be a complete list):
<LinkTo>
@change
@click
@contextMenu
(for thecontextmenu
event)@doubleClick
(for thedblclick
event)@drag
@dragEnd
(for thedragend
event)@dragEnter
(for thedragenter
event)@dragLeave
(for thedragleave
event)@dragOver
(for thedragover
event)@dragStart
(for thedragstart
event)@drop
@focusIn
(for thefocusin
event)@focusOut
(for thefocusout
event)@input
@keyDown
(for thekeydown
event)@keyPress
(for thekeypress
event)@keyUp
(for thekeyup
event)@mouseDown
(for themousedown
event)@mouseEnter
(deprecated, for themouseenter
event)@mouseLeave
(deprecated, for themouseleave
event)@mouseMove
(deprecated, for themousemove
event)@mouseUp
(for themouseup
event)@submit
@touchCancel
(for thetouchcancel
event)@touchEnd
(for thetouchend
event)@touchMove
(for thetouchmove
event)@touchStart
(for thetouchstart
event)<Input>
@click
@contextMenu
(for thecontextmenu
event)@doubleClick
(for thedblclick
event)@drag
@dragEnd
(for thedragend
event)@dragEnter
(for thedragenter
event)@dragLeave
(for thedragleave
event)@dragOver
(for thedragover
event)@dragStart
(for thedragstart
event)@drop
@input
@mouseDown
(for themousedown
event)@mouseEnter
(deprecated, for themouseenter
event)@mouseLeave
(deprecated, for themouseleave
event)@mouseMove
(deprecated, for themousemove
event)@mouseUp
(for themouseup
event)@submit
@touchCancel
(for thetouchcancel
event)@touchEnd
(for thetouchend
event)@touchMove
(for thetouchmove
event)@touchStart
(for thetouchstart
event)@focus-in
(for thefocusin
event)@focus-out
(for thefocusout
event)@key-down
(for thekeydown
event)@key-press
(for thekeypress
event)@key-up
(for thekeyup
event)<Textarea>
@click
@contextMenu
(for thecontextmenu
event)@doubleClick
(for thedblclick
event)@drag
@dragEnd
(for thedragend
event)@dragEnter
(for thedragenter
event)@dragLeave
(for thedragleave
event)@dragOver
(for thedragover
event)@dragStart
(for thedragstart
event)@drop
@input
@mouseDown
(for themousedown
event)@mouseEnter
(deprecated, for themouseenter
event)@mouseLeave
(deprecated, for themouseleave
event)@mouseMove
(deprecated, for themousemove
event)@mouseUp
(for themouseup
event)@submit
@touchCancel
(for thetouchcancel
event)@touchEnd
(for thetouchend
event)@touchMove
(for thetouchmove
event)@touchStart
(for thetouchstart
event)@focus-in
(for thefocusin
event)@focus-out
(for thefocusout
event)@key-down
(for thekeydown
event)@key-press
(for thekeypress
event)@key-up
(for thekeyup
event)
These arguments are no longer necessary – with angle bracket invocations, DOM
event listeners can be registered directly using the {{on}}
modifier. An
invocation passing one or more of these named arguments shall trigger a
deprecation warning similar to this:
~~~~~~~~~~~~~~~~~~~~~~~
or
{{input click=this.onClick}}
~~~~~~~~~~~~~~~~~~
Passing the `@click` argument to is deprecated. Instead, please use the
{{on}} modifier, i.e. `` instead of
`` or `{{input click=...}}`.
Note that these named arguments were not necessarily an intentional part of the component's original design. Rather, these are callbacks that would have fired on all classic components, and since classic components' arguments are set on the component instances as properties, passing these arguments at invocation time would have "clobbered" any callbacks with the same name defined on the component's class/prototype, whether it was intended by the component's author or not.
For instance, the <Input>
and <Textarea>
built-in components implemented
callbacks that would have been clobbered by these named arguments (may not be a
complete list):
@change
@focusIn
@focusOut
@keyDown
@keyPress
@keyUp
Passing these named arguments historically supressed certain behavior of the built-in components, in some cases preventing the components from functioning properly. This was never an intended part of the original design and should be considered a bug.
This bug may be fixed at any time during the transition period – the supression behavior may stop without notice and should not be relied upon. An invocation with these named arguemnts shall trigger a deprecation warning with this additional caveat, similar to this:
~~~~~~~~~~~~~~~~~~~~~~~~~
or
{{input change=this.onChange}}
~~~~~~~~~~~~~~~~~~~~
Passing the `@change` argument to is deprecated. This would have
overwritten the internal `change` method on the component and prevented
it from functioning properly. Instead, please use the {{on}} modifier, i.e.
`` instead of `` or
`{{input change=...}}`.
No Longer Recommended
Changing @tagName
on <LinkTo>
Due to the classic component implementation heritage, the built-in components
historically accepted a @tagName
argument that allows customizing the tag
name of the underlying HTML element.
This was once popular with the <LinkTo>
component for adding navigation
behavior to buttons, table row and other UI elements. The current concensus is
that this is an anti-pattern and causes issues with assistive technologies.
In most cases, the <a>
anchor HTML element should be used for navigational UI
elements and styled with CSS to fit with the design requirements. Ocasionally,
a button may be acceptable, in which case a custom event handler can be written
using the router service and attached using the {{on}}
modifier.
Other edge cases exists, but generally those solutions can be adapted to fufill the requirements. For example, to make a table row clickable as a convenience, the primary column can be made into a link, while a click event handler is attached to the table row to redispatch the click to trigger the link.
Since this feature is no longer recommended, invoking <LinkTo>
with the
@tagName
argument shall trigger a deprecation warning similar to this:
...
~~~~~~~~~~~~~~
or
{{#link-to tagName="div" ...}}...{{/link-to}}
~~~~~~~~~~~~~
Passing the `@tagName` argument to is deprecated. Using a