Skip to content
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

feat(core): Support two-way binding for value on Input elements #55873

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

JeanMeche
Copy link
Member

@JeanMeche JeanMeche commented May 19, 2024

The commit adds runtime support for two-way bindings on input. No Forms imports required this is supported at runtime level. This will only handle strings as value returns a string.

The compiler didn't throw any warnings on value 2-way bindings before, so no changes on this side.

@Component({
  selector: 'app-root',
  standalone: true,
  template: ` <input [(value)]="name" />`,
})
class App {
  name = signal('Angular');
  effect = effect(() =>this.name());
}

@angular-robot angular-robot bot added the detected: feature PR contains a feature commit label May 19, 2024
@JeanMeche JeanMeche force-pushed the feat/input-2-way branch 5 times, most recently from ddca31c to f83703b Compare May 19, 2024 15:09
@JeanMeche JeanMeche marked this pull request as ready for review May 19, 2024 15:30
@pullapprove pullapprove bot requested a review from crisbeto May 19, 2024 15:31
*/
function mapInput2WayBinding(nativeElement: RElement, eventName: string) {
if (nativeElement.tagName === 'INPUT' && eventName === 'valueChange') {
return 'input';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the semantics may be confusing. e.g. Why input and not the change event?

Copy link
Member Author

@JeanMeche JeanMeche May 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input event fires on every keystroke, change only fires on blur/enter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, but why do we choose input and not change? In addition, how can a user tell what event they will get.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would probably mention that in the docs.
About input vs change, we're binding the value property on an HTMLInputElement and the value of this property changes on every input event. I would expect the signal to reflect that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, people might have different expectations- so we should make sure we considering the alternatives as well.

I definitely also do see input valuable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input events also feel like the right choice to me, since this is how ngModel behaves, so it's "consistent."

packages/core/src/render3/instructions/listener.ts Outdated Show resolved Hide resolved
packages/core/src/render3/instructions/listener.ts Outdated Show resolved Hide resolved
@@ -248,6 +250,29 @@ describe('event listeners', () => {
button.click();
expect(fixture.componentInstance.comp).toBeInstanceOf(MyComp);
});

it('should support 2-way binding on input value', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have some tests that cover the more complex input types, like date or number? Also we'd probably need some tests for the template type checking side as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value property will always return a string, we could supporting binding on valueAsNumber & valueAsDate to support those types.

packages/core/src/render3/instructions/listener.ts Outdated Show resolved Hide resolved
@JeanMeche JeanMeche force-pushed the feat/input-2-way branch 4 times, most recently from d4e2c65 to 1761ea5 Compare May 19, 2024 20:41
The commit adds runtime support for two-way bindings on input. No Forms imports required this is supported at runtime level.
The compiler didn't throw any warnings on value 2-way bindings before, so no changes on this side.
function createTwoWayBindingEventMapping(
nativeElement: RElement,
eventName: string,
): {mapperFn: (e: any) => any; eventName: string} | null {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we optimize this structure by making it a tuple ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO not necessary.

@dylhunn dylhunn added area: core Issues related to the framework runtime core: binding & interpolation Issue related to property/attribute binding or text interpolation labels May 22, 2024
@ngbot ngbot bot modified the milestone: Backlog May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime core: binding & interpolation Issue related to property/attribute binding or text interpolation detected: feature PR contains a feature commit
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants