Manipulating Select element on form - javascript

I'm trying to programatically autofill my information on a form like this (Stripe's testing form) however I'm having trouble filling/selecting some of the fields.
For example, merely changing the Node's value attribute is not working for fields like the cardNumber field, and changing the selectedIndex attribute for the country does not have any effect.
Example:
selectedIndex = 40 from another index like 3 gives you Canada, which when done manually, will cause a Postal Code field to appear. However, I'm having trouble achieving this programmatically by just changing theselectedIndex

You can manually dispatch an event:
var select = document.getElementById('billingCountry')
select.dispatchEvent(new Event('change', { 'bubbles': true }))

Related

The use of JavaScript onchange("<function>(this.id)") on c# CheckBox vs other c# Controls

I have a web document that has its fields populated dynamically from c# (.aspx.cs).
Many of these fields are TextBox or HtmlTextArea elements, but some are Checkbox elements.
For each of these I have the ID attribute populated on creation of the field, as well as using .Attributes.Add("onchange","markChanged(this.id)")
This works great on all the fields except Checkbox. So I created a markCheckChange as I discovered that the Checkbox won't accept style="backgroundColor:red" or .style.backgroundColor = "red" type arguments.
I also added an alert and found that the Checkbox is not actually passing the this.id into the parameter for markCheckChange(param) function.
As a result I am getting errors of the type:
unable to set property of undefined or null reference
Why and what is the difference between these controls, and is there a better way to handle this?
I just reviewed the inspect element again, and discovered that the Checkbox control is creating more than an input field of the type checkbox, it is also wrapping it in a span tag, and the onchange function is being applied to the span tag (which has no id) and not to the input tag that has the checkbox id. Whereas for TextBox and HtmlTextArea the input tag is put directly within the cell/td tag, no some arbitrary span tag.
So now the question becomes how to get the onchange function to apply to the input tag for the checkbox rather than the span tag encapsulating it?
Per request:
function markChange(param) {
if (userStatus == "readonly") {
document.getElementById("PrintRecButton").style.display = "none";
document.getElementById("PrintPDFButton").style.display = "none";
alert("Please login to make changes.\n\nIf you do not have access and need it,\n contact the administrator");
exit();
}
else {
document.getElementById(param).style.backgroundColor = "teal";
saved = false;
var page = document.getElementById("varCurrentPage").value;
markSaveStatus(page, false);
}
}
So far the markCheckChange is about the same, until I get it to pass the id correctly, I won't be able to figure out the right way to highlight the changed checkboxes.
I found an alternative.
As I mentioned in the edit to the question, the inspect element feature revealed that the CheckBox type control was creating a set of nested elements as follows:
<span onchange="markChange(this.id)">
<input type="checkbox" id="<someValue>">
<label for="<someValue>">
</span>
Thus when the onchange event occurred it happened at the span which has no id and thus no id was benig passed for the document.getElementById() to work.
While searching for why I discovered:
From there I found the following for applying labels to the checkboxes:
https://stackoverflow.com/a/28675013/11035837
So instead of using CheckBox I shall use HtmlInputCheckBox. And I have confirmed that this correctly passes the element ID to the JavaScript function.

Jquery .on('change' does not detect javascript inputed field

see following snip of code
$(document).on('input','#id1, #id2, #id3', function(){
$id1 = $('#retail').val();
$id2 = $('#tax').val();
$id3 = $('#discount_per_unit').val();
$total = Number($id1) + Number($id2) - Number($id3);
$('#total').val($total);
});
now, user gets to input field for #id1, #id2. but I have a Ajax fill in #id3 for the user depending on conditions. the .on(input or .on(change event only detect user input but not the Ajax input. So is there a way to get jquery to detect Ajax input as well.
basically I have a drop down menu user can pick, and Ajax will take the drop down value to get an additioanl data and auto fill into id3 input field. look something like this.
$('#id3').val($somevalue);
but my .on("change" does not detect when user picked a different drop down option so the #id3 is updated but my calcuation that uses id1 though id3 did not update unless I change something on id1 or id2.
You update $('#id3').val($somevalue); didn't trigget any event, they are based on user's actions.
If you want to manually trigger one you can do
$('#id3').val($somevalue).trigger('change') // or 'input'

How to post input fields conditionally

I have an MVC (Razor) web app. The form has 2 fields, one dropdown box (Kendo) and one input field for a date.
After the user makes a change on the dropdown, my 2nd input field is enabled or disabled based on the chosen type in the dropdown box. When the input field is disabled I fill the input with a default value.
When the user submits the form, I only get 2nd form field value posted in the viewmodel when the 2nd field is enabled, when disabled the value is not posted. I know this a common pattern in HTML, that disabled fields are not part of the POST.
My question: how can I solve this issue to get the value POSTed when the field is disabled ? It should be done in JS...
I had a similar requirement, what i did was, created a class , which would make the text box appear like disabled, by removing mouse events and styling a bit
[https://codepen.io/DawsonMediaD/pen/Dqrck][1]
or
Bit tricky, just before the post , enable all of them
Fixed it, in the onchange handler of the dropdown box attach this JS code:
var defaultDateValue = "2017-01-04"; //just for demo
var $effectiveToInput = $("##Html.IdFor(m => m.EffectiveToDate)");
$effectiveToInput.parent().append("<input type=\"hidden\" name=\"#Html.NameFor(m => m.EffectiveToDate)\" id=\"#Html.NameFor(m => m.EffectiveToDate)\" value=\"" + defaultDateValue +"\" />");
And for the other types, i clear the hidden fields with checks:
function removeHiddenEffectiveToDateField() {
var $effectiveToInput = $("##(Html.IdFor(m => m.EffectiveToDate))[type = hidden]");
if (null !== $effectiveToInput) {
$effectiveToInput.remove();
}
}

ASP MVC binding two controls to one field

In my view model I have a field. This field can be selected from a drop down list or entered in a textbox. I have two radio buttons which allows to select between drop and textbox.
<div class="frm_row" id="contractorRow">
#Html.RadioButton("IsContractorNew", "false", true)
#Html.Label(#Resources.SomeLabels.Existing)
#Html.RadioButton("IsContractorNew", "true", false)
#Html.Label(#Resources.SomeLabels.New)
<div class="frm_row_input" id="contractorDropDownList">
#Html.DropDownListFor(model => model.CONTRACTOR, Model.Contractors)
#Html.ValidationMessageFor(model => model.CONTRACTOR)
</div>
<div class="frm_row_input" id="contractorTextBox" style="display: none;">
#Html.TextBoxFor(model => model.CONTRACTOR)
#Html.ValidationMessageFor(model => model.CONTRACTOR)
</div>
</div>
I prepared a javascript code for hiding, showing and clearing controls while selecting radio buttons. The problem is - field is bound only to the first control (drop down list).
EDIT:
I solved this problem by creating one hidden field and scripting whole logic to bind active control with it and therefore with the model. Anyway if anyone knows simpler solution, please post it.
I know this is an old question, but for those dealing with this issue, here's a solution:
Explanation
When a form is submitted, input elements are bound to the model by their name attribute. Let's say you use HTML helpers to generate your form, and you generate two input fields which bind to the same property on the model. When rendered to the DOM, they both have the same name attribute.
<input name="Passport.BirthPlace" id="birthPlaceDropDown" ... >
<input name="Passport.BirthPlace" id="birthPlaceInfoTextbox" ... >
When the form is submitted, it will bind the first (in the DOM) input it finds to Passport.BirthPlace
A Solution
The quick and easy way to fix this is to use JQuery to change the name of the field you don't want bound on submit. For me, I use a checkbox to toggle which field shows. When the checkbox changes, I hide one control, change its name attribute, and show the other one (and change it's name attribute to Passport.BirthPlace) It looks like this, basically:
First, I run this on document ready
$('#birthPlaceInfoTextbox').attr('name', 'nosubmit'); // Change name to avoid binding on inactive element
Then, I create a listener for my checkbox which toggles which control should be bound:
$('#notBornUSCheckbox').change(function() {
if (this.checked) {
// Not born us was checked, hide state dropdown and show freeform text box
$('#stateDropDownSection').addClass('d-none'); // Hide drop down
$('#birthPlaceDropDown').attr('name', 'nosubmit'); // Change name to something other than Passport.BirthPlace
$('#birthPlaceInfoTextbox').attr('name', 'Passport.BirthPlace'); // Set this one to be bound to the model
$('#stateTextboxSection').removeClass('d-none'); // Show the textbox field
} else { // Opposite of above lines
$('#stateDropDownSection').removeClass('d-none');
$('#stateTextboxSection').addClass('d-none');
$('#birthPlaceInfoTextbox').attr('name', 'nosubmit');
$('#birthPlaceDropDown').attr('name', 'Passport.BirthPlace');
}
});
Instead of using Razor #Html.TextBoxFor... for your textbox, you could try using raw HTML e.g. <input />. Also, have your JavaScript code remove the other field from the DOM entirely when a radio button is clicked, before submitting the form.

Dynamically creating an input field with disabled = true is setting null values to zero

I have a timesheet table. At the bottom of the table there is a button which allows me to add a row. Understandably, all the cells in the new row start off empty. The JavaScript uses:
txtFld.setAttribute('value', '');
to do so.
However, in some situations I want some of the new fields to show up but be disabled so I (in those situations) add in:
txtFld.setAttribute('disabled', 'disabled');
The problem is that, when doing this, after submission, when the table re-renders itself, all those empty values show up as zeroes instead of empty strings. As far as calculations go, that's fine, but I don't want rows of zeroes. I want empty cells. If I take out the disabled part, it works fine.
I've temporarily remedied this by, instead of using disabled, using readonly, which seems to give me the desired results. The only problem is that, while the text field remains non-editable, the user CAN place the cursor inside the box. I want the cleaner, "can't even click in here" that the disabled gives me.
Any thoughts on why the disabled feature is doing this and how I can use disabled without the resulting row of zeroes?
For the record, I've mixed and matched every combination of:
txtFld.setAttribute('value','');
txt.setAttribute('value', null);
txtFld.value = '';
txtFld.value = null;
with
txtFld.setAttribute('disabled');
txtFld.setAttribute('disabled', 'true');
txtFld.setAttribute('disabled', 'disabled');
txtFld.disabled = 'true';
txtFld.disabled = 'disabled';
that I can think of with the same results (or worse) every time.
Thanks.
When a field is disabled, it's not included in the form parameters sent to the server.
In new browsers (IE11+, and pretty much everything else) you can use CSS to disable pointer events on the element:
txtFld.readonly = true;
txtFld.style.pointerEvents = 'none';
That'll make the element simply not respond to any clicks. (Here is a jsfiddle.) Because it's not disabled, a form POST will send the empty field to the server.
You should disable fields by setting the "disabled" property of their DOM nodes to true (the boolean constant, not the string).
txtFld.disabled = true; // disables field
txtFld.disabled = false; // enables field
The "disabled" property is treated as a boolean, so setting it to any string value (other than the empty string) will set it to true:
txtFld.disabled = "false"; // disables field
Another thing you can do to exploit the real disabled browser behavior and have empty parameters posted to the server is to use pairs of inputs:
<input type=text name=whatever data-companion=whatever-c> <!-- visible input -->
<input type=hidden name=whatever id=whatever-c> <!-- invisible input -->
Now whenever you enable the text field, you disable the hidden input, and vice-versa. That way there's always something posted.

Categories