I have a custom dropdown componant. Within this component, I set a custom getter and setter shown below:
Object.defineProperty(this.DropDownInputTarget, 'value', {
get: function() {
return this.dataset.inputValue ?? nativeInputGetter.call(this);
},
set: function(value: string){
nativeInputSetter.call(this, value);
}
});
When using this in code or via the inspector console, I get the expected result. But when I am getting the form data via new FormData(SomeForm)
, the value is always null. Is there something I need to do for this to work as expected?
Example from inspector:
code: document.querySelector('#Item1_ShippingInfo_StoreOptions_OtherLocationId').value
response: "BRXSL"
How I get my form data:
const formData = new FormData(shippingForm);
All other values from the other inputs are retrieved correctly.
As far as why I am using a custom getter, this is for a custom drop down component. The actual value of the selected item is different from the displayed value. I keep the actual value in a data attribute. This is what the custom getter retrieves.
Here is a picture of what the values look like in the console. Note that I am getting null in the FormData object, but a value when I get the input.value. And this is what it looks like if I don't use Ajax to submit the form:
I do have a work-around, but it is less than ideal. It requires me to set the value I am missing manually after I create the formData
object.
const formData = new FormData(shippingForm);
formData.set('Item1.ShippingInfo.StoreOptions.OtherLocationId',
shippingForm.querySelector<HTMLInputElement>('#Item1_ShippingInfo_StoreOptions_OtherLocationId').value);
While using internals.setFormValue()
can work, this requires the input to be a custom input. This way you can call HTMLElement.attachInternals()
.
After that, you need to make sure the custom element class has this variable defined at the class level: static formAssociated = true;
so that it will be picked up when creating a new FormData.
If your input is not a custom element, this approach will not work as HTMLElement.attachInternals()
will not work in built in types.
I chose to not go this route because:
Solution: Add a hidden input element. This is the input element I will bind to in c# as well as update the value for when I select an item.
<div class="select-container">
<input type="text" class="form-control" placeholder="Other Location" data-custom-validation="dropdownValidation" data-dropdown-action="search" data-dropdown-input/>
<input type="hidden" asp-for="@Model.Location" />
<!-- Additional HTML for the select componant -->
<div>
In the above example, the hidden input is after the visible one. The visible input will still show what is "selected" while the hidden input gets updated to the current value I want to be submitted. Because the visible input has no name or value, it will not be captured when creating the form data.