Skip to content

Commit 31340d5

Browse files
authored
Merge pull request #997 from NullVoxPopuli/make-on-built-in
2 parents bcee6cc + f7cdd5d commit 31340d5

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

text/0997-make-on-built-in.md

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
---
2+
stage: accepted
3+
start-date: 2023-12-22T00:00:00.000Z
4+
release-date: # In format YYYY-MM-DDT00:00:00.000Z
5+
release-versions:
6+
teams: # delete teams that aren't relevant
7+
- framework
8+
- learning
9+
- typescript
10+
prs:
11+
accepted: https://github.com/emberjs/rfcs/pull/997
12+
project-link:
13+
suite:
14+
---
15+
16+
<!---
17+
Directions for above:
18+
19+
stage: Leave as is
20+
start-date: Fill in with today's date, 2032-12-01T00:00:00.000Z
21+
release-date: Leave as is
22+
release-versions: Leave as is
23+
teams: Include only the [team(s)](README.md#relevant-teams) for which this RFC applies
24+
prs:
25+
accepted: Fill this in with the URL for the Proposal RFC PR
26+
project-link: Leave as is
27+
suite: Leave as is
28+
-->
29+
30+
# Make `{{on}}` a built in modifier
31+
32+
## Summary
33+
34+
Today, when using gjs/gts/`<template>`, in order to bind event listeners, folks _must import_ the `{{on}}` modifier.
35+
Because event listening is so commonplace, this is a grating annoyance for developers.
36+
37+
This RFC proposes that `{{on}}` be built in to `glimmer-vm` and not require importing.
38+
39+
## Motivation
40+
41+
Given how common it is to use the `{{on}}` modifier:
42+
43+
```gjs
44+
import { on } from '@ember/modifier';
45+
46+
<template>
47+
<button {{on 'click' @doSomething}}>
48+
click me
49+
</button>
50+
51+
<form {{on 'submit' @localSubmit}}>
52+
<label
53+
{{on 'keydown' @a}}
54+
{{on 'keyup' @a}}
55+
{{on 'focus' @a}}
56+
{{on 'blur' @a}}
57+
>
58+
</label>
59+
60+
<button>
61+
submit
62+
</button>
63+
</form>
64+
</template>
65+
```
66+
67+
It should be built in to the templating engine, Glimmer, so that folks don't need to import it.
68+
69+
There is precedence for this already as the following are already commonplace and built in:
70+
- `(helper)`
71+
- `(modifier)`
72+
- `(component)`
73+
74+
It's historically been the stance that,
75+
76+
"If it can be built in userspace, it should be, leaving the framework-y things to be only what can't exist in userspace"
77+
78+
But to achieve the ergonomics that our users want, we should provide a more cohesive experience, rather than require folks import from all of (in the same file):
79+
- `@glimmer/component`
80+
- `@glimmer/tracking`
81+
- `@ember/modifier`
82+
- `@ember/helper`
83+
- `ember-modifier`
84+
- `ember-resources`
85+
- `tracked-built-ins`
86+
87+
Some of the above may unify in a separate RFC, but for the template-utilities, since the modules that provide them are already so small, it makes sense to inherently provide them by default. Especially as we can target strict-mode only, so that we don't run in to the same implementation struggles that built-in [Logical Operators](https://github.com/emberjs/rfcs/pull/562), [Numeric Comparison Operators](https://github.com/emberjs/rfcs/pull/561), and [Equality Operators](https://github.com/emberjs/rfcs/pull/560) have faced.
88+
89+
<details><summary>some context on those RFCs</summary>
90+
91+
The main problem with adding default utilities without strict-mode is that it becomes very hard to implement a way for an app to incrementally, and possibly per-addon, or per-file, to adopt the default thing due to how resolution works. Every usage of the built in utility would also require a global resolution lookup (the default behavior in loose mode templates) to see if an addon is overriding the built ins -- and then, how do you opt in to the built ins, and _not_ let addons override what you want to use?
92+
93+
With gjs/gts/`<template>`, this is much simpler, as in strict-mode, you can check if the scope object defines the helpers, and if not, use the built in ones.
94+
95+
This strategy of always allowing local scope to override default-provided utilities will be a recurring theme.
96+
97+
</details>
98+
99+
---------------
100+
101+
_Making `on` a built-in will help make writing components feel more cohesive and well supported, as folks will not need to cobble together many imported values_
102+
103+
----------------
104+
105+
## Detailed design
106+
107+
This change would affect strict-mode only. This is so that today's existing code that imports `on` from `@ember/modifier` will still work due to how values defined locally in scope override globals.
108+
109+
The behavior of `on` would be the same as it is today, but defined by default in the `glimmer-vm`.
110+
111+
112+
`on` will be a keyword, and for backwards compatibility, this will require that keywords, in strict mode, be overrideable by the strict-mode scope bag.
113+
114+
115+
## How we teach this
116+
117+
Once implemented, the guides, if they say anything about gjs/gts/`<template>` and `on` by the time this would be implemented, would only remove the import.
118+
119+
## Drawbacks
120+
121+
People may not know where `on` is defined.
122+
- counterpoint: do they need to?, we are defining a lanugage, trying to make it ergonomic.
123+
124+
We need to allow keywords to be overridable in Glimmer -- this is a behavior most languages do not allow.
125+
126+
## Alternatives
127+
128+
- Use a prelude
129+
- preludes were mentioned during the initial exploration of strict-mode templates, and were decided against, because addons would not be able to assume a prelude exists, as apps could define their own, and this sort of re-introduces the app-tree-merging behavior that we've been trying to get away from.
130+
131+
- Use an alternate syntax: `on:click={{handler}}` or `on:{eventname}={{value}}`
132+
- This would be even more ergonomic, and I think we should do this syntax anyway, but may take longer to implement. -- thought would not require glimmer allow the scope bag to overrid keywords.
133+
134+
135+
## Unresolved questions
136+
137+
- What happens if we want to remove a keyword? (like `mut`)
138+
- same as today, we only need to commit to a major to remove the keyword in and then do it - providing ample deprecation time, ending with the final removal.

0 commit comments

Comments
 (0)