-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Modified EditForm to return _fixedEditContext via the EditContext parameter #24007
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
Conversation
…ameter. Also added some tests to cover the new functionality
| private readonly Func<Task> _handleSubmitDelegate; // Cache to avoid per-render allocations | ||
|
|
||
| private EditContext? _fixedEditContext; | ||
| private EditContext? _providedEditContext; |
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.
I'm not super familiar with this area, do we need the extra field? Or can we make _providedContext hold the right value whether it received a Model or a Context
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.
The _providedEditContext field is there to track if the EditContext was provided directly via the EditContext parameter. This mean we don't break the current functionality in the OnParametersSet method which checks if the developer has provided a value for both EditContext and Model.
|
|
||
| namespace Microsoft.AspNetCore.Components.Forms | ||
| { | ||
| public class EditFormTest |
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.
Nice!
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.
Thanks! I hope the tests are ok, its my first go at writing them.
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.
These tests are looking great. Good stuff!
| public EditContext? EditContext | ||
| { | ||
| get => _fixedEditContext; | ||
| set => _providedEditContext = value; | ||
| } |
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.
I think this risks being a little weird, because I know we don't recommend people write to parameter properties directly, but if someone does this will be kind of bizarre. If you write a value to this property then try to read it back, you'll get a totally different value :)
Would it be possible instead to do something like:
bool _hasSetEditContextExplicitly;
[Parameter]
public EditContext? EditContext
{
get => _fixedEditContext;
set
{
_fixedEditContext = value;
_hasSetEditContextExplicitly = true;
}
}... and then inside OnParametersSet:
if (_hasSetEditContextExplicitly && Model != null)
{
throw "Don't set both"
}
else if (EditContext == null && Model == null)
{
throw "Set at least one"
}Sorry for not noticing this earlier on the original proposal!
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 is why I can't be left alone to review things after lunch 😄
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 makes sense, I'll make the change
| var returnedEditContext = editFormComponent.EditContext; | ||
|
|
||
| // Assert | ||
| Assert.NotNull(returnedEditContext); |
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.
| Assert.NotNull(returnedEditContext); | |
| Assert.Same(editContext, returnedEditContext); |
|
This is a patch with the changes in the ref assembly, it's not an API change, but the tool is complaining, so we just need to apply that to keep the build happy |
|
@javiercn Is that patch something I need to do? If so what do I need to do? :) |
| get => _fixedEditContext; | ||
| set | ||
| { | ||
| if (value != null) |
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.
I'm not sure if this was the right thing to do now I'm looking at it here. This would mean that once an EditContext has been set it can't be set back to null. Is that a scenario that should be catered for?
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.
It's never going to be, is it? even if you set a model, wouldn't that be the case?
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.
I can't think of a reasonable scenario where you would pass in an EditContext and then later decide to set it to null. But just wanted to check
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.
I have the same feeling, but @SteveSandersonMS is the expert on this area, so I would defer the final say to him
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.
If you want a null check, could you throw ArgumentNullException? I think we shouldn't ignore the null value. Either accept it, or throw :)
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.
(Of these options, I'd prefer throwing, since there's no real value in letting people set it back to null)
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.
I added this check so that _hasSetEditContextExplicity doesn't get set to true when the value is null. Perhaps I should adjust the code to this:
public EditContext? EditContext
{
get => _fixedEditContext;
set
{
_fixedEditContext = value;
_hasSetEditContextExplicity = value != null ? true : false;
}
}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.
Looks like that would work to me.
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.
Ok I've push the update
|
@chrissainty you can apply the patch manually (just download it and apply the changes) if you know how, or if you do it the "manual way" inspect the patch, open the file and replace the line manually. This is part of how we generate reference assemblies for compilation and sometimes it causes this issues. We are working on making this happen automagically I believe |
| throw new InvalidOperationException($"{nameof(EditForm)} requires a {nameof(Model)} " + | ||
| $"parameter, or an {nameof(EditContext)} parameter, but not both."); | ||
| } | ||
| else if (EditContext == null && Model == null) |
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.
Should this now be else if (!_hasSetEditContextExplicitly && Model == null) ?
Because the rule is: you must supply a model if and only if you didn't supply an edit context.
In the event where you:
- First supplied a non-null model
- Then on the next render supplied a null model
Then we'd want to throw I think, but the existing logic wouldn'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.
Yes, agreed. I'll update it.
| // Update _fixedEditContext if we don't have one yet, or if they are supplying a | ||
| // potentially new EditContext, or if they are supplying a different Model | ||
| if (_fixedEditContext == null || EditContext != null || Model != _fixedEditContext.Model) | ||
| if (_fixedEditContext == null || (!_hasSetEditContextExplicitly && Model != _fixedEditContext.Model)) |
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.
Nitpick: I think this could be simplified to:
| if (_fixedEditContext == null || (!_hasSetEditContextExplicitly && Model != _fixedEditContext.Model)) | |
| if (!_hasSetEditContextExplicitly && Model != _fixedEditContext?.Model) |
... because if _hasSetEditContextExplicitly then we know _fixedEditContext != null.
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.
Also the comment above it is slightly out of date now
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.
Strictly speaking the check could be expressed as:
if (Model != null && Model != _fixedEditContext?.Model)(because we know that if Model != null, then _hasSetEditContextExplicitly is false otherwise we would already have thrown above)
Arguably this is a more natural phrasing because it's just stating that if you give us any new model, we want to use it.
|
Thanks very much for the updates, @chrissainty! I think this is really close to being done now. One final thought: the name |
|
Give me 2 minutes @SteveSandersonMS, I'll get it done! :) |
|
Awesome, thanks! @captainsafia @pranavkm Can I leave it with one of you to merge when the tests pass and if you're happy with it? Up to you whether you also want to ask for/wait for this update too. |
|
@SteveSandersonMS @captainsafia @pranavkm I've addressed the last comment, all should be good now :) |
Thanks, Chris! Taking a look now. |
captainsafia
left a comment
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.
Looks like all the feedback has ben addressed here. Thanks for adding the tests!
SteveSandersonMS
left a comment
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.
Brilliant. Thanks @chrissainty!
|
My pleasure! This first sprint has been awesome, I hope we can do it again, soon 😀 |
|
@chrissainty Thank you for the contribution! Your pull request has been merged! |
EditContextparameter to return_fixedEditContext_providedEditContextwhich stores anyEditContextprovided by the developer. This means we don't break existing functionality.OnParametersSetto use the new_providedEditContextfield instead of theEditContextpropertyEditFormfunctionality@SteveSandersonMS tagged for review
Addresses #12238
Addresses #23354