-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Initial implementation of model inputs #54252
Conversation
fbf7f58
to
8408f50
Compare
8408f50
to
cde8507
Compare
Questions:
|
|
bfbb7c1
to
e17685b
Compare
packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts
Outdated
Show resolved
Hide resolved
e17685b
to
1d2606a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall, mostly nits/questions. Nice! 🎉
@@ -199,6 +199,33 @@ runInEachFileSystem(() => { | |||
.toContain(`inputs: { data: [i0.ɵɵInputFlags.SignalBased, "data"] }`); | |||
}); | |||
|
|||
// TODO(crisbeto): we may not want to support this combination. Will discuss with the team. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good conversation. I believe we want to support use-cases where the local "state" might be desychronized from the parent. There is a good issue about people asking for this- although in practice we couldn't come up with a good scenario where users may not want to properly synchronize parent & component (e.g. Dir#expanded
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This combination is fine - there's an input and output of the right shape for two-way binding. We can't enforce that components conform to the two-way binding contract.
ts.isAsExpression(node.left.expression.expression) && | ||
isAccessExpression(node.left.expression.expression.expression)) { | ||
assignment = node.left.expression.expression.expression; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe already planned as a follow-up: Can you please add a test for the language service. Definition + completions? I invested a lot in writing tests here and I think we should continue doing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's one of my points for the follow-up. I just wanted to get all the foundations in place in this PR.
packages/compiler-cli/src/ngtsc/typecheck/src/type_check_block.ts
Outdated
Show resolved
Hide resolved
1d2606a
to
74f8d69
Compare
Addresses the feedback from angular#54252.
I've reworked the TCB to avoid some regressions. Also addressed all the feedback in the last commit. |
standalone: true, | ||
}) | ||
export class TestDir<T> { | ||
value = model.required<T>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also have a test to ensure the value
property is inferred properly. This is a follow-up I guess?
Addresses the feedback from angular#54252.
@JeanMeche |
I know things aren't completed yet, but is there anything planned at framework level for forms? Or is the following method the way to go for the foreseeable future? <input [ngModel]="signal()" (ngModelChange)="signal.set($event)"> |
@wartab yes as classical prop as signal, for now I'm doing it this way |
@JeanMeche so is there another directive for model? |
@sysmat I just tried your example with the RC and it seems to work. See https://stackblitz.com/edit/stackblitz-starters-dcjjnw?file=src%2Fmain.ts @wartab two-way binding to a signal is supported with this change. You should be able to do |
Really cool, thank you very much |
@crisbeto yes it works with signal, but not with model is a bit of mystery to me why not with model, probably I'm missing something here |
It works for me with |
|
It may be worth clearing your |
@crisbeto I delete lock, re install, and also using "builder": "@angular-devkit/build-angular:application", |
@crisbeto in your stackblitz you are using, is this ok
|
my component is loaded by router, but this shouldn't be problem, when it works with signal
|
Hmm that's weird. Here's a fork with 17.2 of the CLI: https://stackblitz.com/edit/stackblitz-starters-9pipk1?file=package.json |
Following up here: we've released version 17.2.0-rc.1 to resolve the type checking error that @JeanMeche flagged above. |
<select [(ngModel)]="selectedModel">
<option [value]="7">7</option>
<option [value]="14">14</option>
</select>
<hr />
Selected value: {{ selectedModel() }}
....
version = VERSION.full;
selectedModel = model(7);
|
|
I take fork of @crisbeto with routing and it is not working on route (model.ts), but work in main |
I'm guessing this is an issue when setting the value through |
yes, the withComponentInputBinding() is the problem |
If I have a component that has no inputs but have withComponentInputBinding() enabled. Declaring a model such as Unless I set the value in ngInit: modelName.set('Model Scott'); |
@scottwalter-nice but why should be model bound to router, for that we have input |
I was probably misusing the shiny new model when input or a simple Signal would have sufficed. I guess we need a good explainer on basic SIgnal vs model. |
@sysmat looking into your Stackblitz: I think the problem is that you aren't setting a value for the |
To be honest I’m confused between signal inputs and model. I originally thought model was for two way binding, but i can do that with regular signals on 17.2 What is the use case of model vs signal inputs? |
|
yes I also used new model for ngModel field initially but it didn't work with 'withComponentInputBinding', should have tried this normal signal first. I assume its not meant for using with [(ngModel)]. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Adds support for model inputs in the framework.
model()
returns a writable signal that implicitly defines a input/output pair that can be used either in two-way bindings to keep two values in sync or by binding individually to the input and output. When the value of themodel
changes, it will emit an event with the current value.Furthermore, these changes expand two-way bindings to accept
WritableSignal
. This will make it easier to transition existing code to signals in a backwards-compatible way.Example:
Note: with these changes model inputs should be mostly working. There are a few places where things will be improved in a follow-up PR:
ModelSignal.subscribe
.twoWayProperty
instruction is called.applyValueToInputSignal
fromMODEL_SIGNAL_NODE
.input()
is mixed with@Output()
in a two-way binding.