The problem I have :
I click "add"
I select 2nd option
I click "add"
Problem : my first select-list's selected option index = 0;
This should not happen, but I can't figure out why it does it anyway. Can anyone tell me what I did wrong?
<script type="text/javascript">
function add(){
var div =document.getElementById('ruletemplate').cloneNode(true);
document.getElementById('rules').innerHTML += div.innerHTML;
return false;
}
</script>
<div id="ruletemplate" style="display: none;">
<div >
<label for="rule">Rule</label>
<select name="rules[][option]">
<option>MAX PERS</option>
<option>MIN PERS</option>
</select>
<input name="rule[][amount]" type="text"/>
</div>
</div>
<form>
<div id="rules" >
</div>
<a id="addRule" href="" onclick="javascript: add(); return false;">add</a>
<input type="Submit" value="Save" />
</form>
The reason it is doing that is you are setting the innerHTML which means the entire thing is reparsed. You will need to append the element to container instead. Try this it should keep each select's position.
function add(){
var div =document.getElementById('ruletemplate').cloneNode(true);
div.style.display='block';
document.getElementById('rules').appendChild(div);
return false;
}
The option element maintains its current selected state with the selected javascript property (not to be confused with the selected attribute, which corresponds to default selected state).
This isnt cloned - so you would have to update the selection manually
Note - you cannot have duplicate ids on a single document - when you clone you element you are duplicating ids
In some browsers (Firefox, Chrome..) the DOM object is not updated (the text input with its value and the selected option with the "select" attribute), so when you call innerHTML you get the original structure without values.
You have to force the DOM update of the object, like this: http://dev-answers.blogspot.it/2007/08/firefox-does-not-reflect-input-form.html
Related
I have two divs with same class names with one input inside each. First one has id, second - no, I need get closest input to my input with id. I can't set an id to second input, or change class names of divs.
HTML -
<div class="picker">
<input id="myInput"/>
</div>
<div class="picker">
<input/> <-- which I need to get ->
</div>
I have tried to use something like below, but, this operation returns me the first input.
$("#myInput").closest("input")
So you need to pick parent the "picker" and then you need to pick the next "picker" and then find the input.
const inp = $("#myInput").closest('.picker').next('.picker').find('input');
inp.val('found it');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="picker">
<input id="myInput" />
</div>
<div class="picker">
<input/>
<-- which I need to get ->
</div>
I have a form where there is a an input. The user can click an add button and another input will appear under it and so on.
The problem I am having is how do I add an input to the DOM on a click event.
My first thought was using an ngFor or v-for (I'm using both, answer can be in either). When I click the add button, it increments a counter and the counter is then pushed into an array. Then using the for it will display the inputs.
let inputs = 0;
addInput() {
this.inputs++;
this.criteria.push(this.inputs);
}
<button #click.prevent='addInput'>Add input</button>
<input type='text' value='Default Input'>
<div v-for="input in inputs" v-bind:key="input">
<input type='text'>
</div>
It works as originally thought. A new input appears when the button is clicked.
The problem occurs when I add a second input, enter a value, then add a third input. The second input's value is reset to blank.
How can I implement this feature, adding inputs on click, but saving the values on the previous inputs?
Thanks.
If you bind the value of the input (using v-model) to a value in your inputs array, it should keep your values - even when adding a new input.
let inputs = [];
addInput() {
this.inputs.push({value: ""});
}
<button #click.prevent='addInput'>Add input</button>
<input type='text' value='Default Input'>
<div v-for="(input, index) in inputs" v-bind:key="index">
<input v-model="input.value" type='text'>
</div>
When a user presses the Save Button inside a document on click event in jQuery, the value of is stored inside a hidden input. I'm struggling to get the value of this input to display inside an onclick event inside the link below the input to be able to detect the value and delete the item if the user requires. I need to achieve this without having to refresh the page.
$(document).on('click','.addItem', function(){
$('<div class="col3">\
<input type="hidden" class="itemId" name="itemId[]" value="">\
<a class="rowDeleteButton" onclick="onclick="deleteItem($(this))">Delete Button</a>\
<div class="saveButton rowSave">Save Button</div>\
</div>')
});
I require after the Save Button has been pressed that the value stored inside the value="" of the hidden input is also stored inside the onclick event for the Delete Button link.
You have issue in
onclick="onclick="deleteItem($(this))
I think simply passing this to the function is enough. I also prefer Template literals.
You can try the following way:
$(document).on('click','.addItem', function(){
$(this).append(`<div class="col3">
<input type="hidden" class="itemId" name="itemId[]" value="hiddenTestValue">
<a class="rowDeleteButton" onclick="deleteItem(event,this)">Delete Button</a>
<div class="saveButton rowSave">Save Button</div>
</div>`)
});
function deleteItem(e, el){
var hdInput = $(el).parent().find('.itemId');
console.log('value before:',hdInput[0].value);
hdInput[0].value = '';
console.log('value after:',hdInput[0].value);
e.stopPropagation();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="addItem">Test</div>
When I return the value from the javascript function on the onClick event, it is getting inserted but the form refreshes again and I lose the selection and the values that I have inserted.
Why does this happen and how can i avoid it?
Below is a sample of my code:
<form id="lengthConvert">
<p><b>Enter a value : </b></p><input type="number" name="inputValue" />
<p><b>Convert from : </b></p>
<select name="fromUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<p><b>Convert to : </b></p>
<select name="toUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<br/><p id="Output"></p>
<button type="submit" form="lengthConvert" value="Submit" onclick="getElementById('Output').innerHTML=convert()">Convert</button>
</button>
</div>
</body>
</html>
<script>
function convert(){
var value = document.getElementsByName('inputValue')[0].value;
var fromUnit= document.getElementsByName('fromUnit')[0].value;
var toUnit= document.getElementsByName('toUnit')[0].value;
if(fromUnit==toUnit){
return value;
}
}
</script>
when I am returning the value from the javascript method on onclick event, it is getting inserrted but the form refreshes again and I am loosing all the selection and values which i have inserted.
Why? and how can i avoid that?
When you click the button you're submitting your form because you're not doing anything to stop the default behavior. Change
<button type="submit"...
to
<button type="button"...
As a side note, your HTML needs to be fixed as you have an extra </button>, no closing </form>, and an unopened </div>. Also, your function doesn't appear to do any actual conversion.
You need to do two things:
Pass event object from onclick() function
Prevent form submission inside convert function by using preventDefault();
function convert(e) {
e.preventDefault();
var value = document.getElementsByName('inputValue')[0].value;
var fromUnit = document.getElementsByName('fromUnit')[0].value;
var toUnit = document.getElementsByName('toUnit')[0].value;
if (fromUnit == toUnit) {
return value;
}
}
<form id="lengthConvert">
<p><b>Enter a value : </b></p><input type="number" name="inputValue" />
<p><b>Convert from : </b></p>
<select name="fromUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<p><b>Convert to : </b></p>
<select name="toUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<br/>
<button type="submit" form="lengthConvert" value="Submit" onclick="getElementById('Output').innerHTML=convert(event)">Convert</button>
<div id='Output'></div>
</form>
You are submitting your form, which causes the page to reload, thus wiping out whatever was updated on it prior to the submit. Instead, you'll want to use a regular button (<button type="button">).
But, beyond that, your code is very outdated and inefficient. .getElementsByName() is generally not recommended for performance reasons, but in your case it's even worse because you only want one element, so you're scanning the entire DOM, getting a set of matching elements and then throwing away all but one of them. Use the modern .querySelector() and .querySelectorAll() for most of your DOM searches.
Your HTML is also invalid because you have an extra closing button tag an no closing form tag.
Also, the use of inline event attributes (onclick) should not be used. This is a 25+ year old technique that just won't die because it's easy and people just copy/paste other code they've found that seems to work. There are a lot of reasons not to do this.
There are a number of other concerns in your code as well. Here's your solution, cleaned up and modernized (make sure to see the HTML, CSS, and JS comments):
/* We can style the rows any way we want: */
div.row { margin-top:1em; margin-bottom:1em; font-weight:bold; }
<form id="lengthConvert">
<!--
The us of <p> elements here is really not correct as they mean paragraph, which
itself means "thought or idea". You are just using them for vertical spacing, and
we should not be using HTML for presentation, that's for CSS. Along the same vein,
<b> isn't appropriate here either because you are just using it for presentation.
Instead, a semantically neutral tag like <div> should be used for rows.
CSS classes can be added to control the presentation
-->
<div class="row">Enter a value : </div>
<div class="row">
<!--
Don't use self-termination syntax <tag />.
That syntax is very old an only applies to XHTML, which is not used
very much these days. Adding that syntax buys you nothing.
-->
<input type="number" name="inputValue">
</div>
<div class="row">Convert from :</div>
<div class="row">
<!-- You don't need to set a value for an <option> when
you want the value of an <option> to be the same as
the text of the <option>. The text of the selected
<option> will become the value of the <select> by default.
-->
<select name="fromUnit">
<option>Centimeter</option>
<option>Meter</option>
<option>Kilometer</option>
<option>Miles</option>
</select>
</div>
<div class="row">Convert to :</div>
<div class="row">
<select name="toUnit">
<option>Centimeter</option>
<option>Meter</option>
<option>Kilometer</option>
<option>Miles</option>
</select>
</div>
<div class="row" id="Output"></div>
<!-- The form attribute is only used when a form element is placed outside of the
form it relates to.
Also, don't use inline HTML event attributes.
And, there is no need to add a value attribute unless you want the value
to be something different than the text of the element.
-->
<button type="button">Convert</button>
</form>
<script>
// Get all the element references you know you'll need
let btn = document.querySelector("button[type='button'");
let output = document.getElementById('Output');
// You only have one element with a name of "inputValue". Use
// .querySelector() with a valid CSS selector as an argument
// to find the first item that matches the selector.
// Also, don't assign variables to properties of an element because
// if you ever want to get a second property value, you'll have to
// scan the document all over again for the element. Just store a
// reference to the element itself, then you can access that as often
// as you like.
let input = document.querySelector("input[name='inputValue']");
let fromUnit = document.querySelector("select[name='fromUnit']");
let toUnit = document.querySelector("select[name='toUnit']");
// Set up your event handling in JavaScript, not HTML
btn.addEventListener("click", convert);
function convert(){
console.log(fromUnit.value, toUnit.value);
if(fromUnit.value == toUnit.value){
// Use .textContent when getting/setting text that
// does not contain any HTML. Its's quicker and
// safer.
output.textContent = input.value;
}
}
</script>
Is it somehow possible to restore only a part of a form? For example I want to reset everyhting in fieldset #1 but keep all other values in fieldset #2:
<form>
<fieldset id="1">…</fieldset>
<fieldset id="2">…</fieldset>
</form>
I could of course use a JavaScript-/jQuery-solution like this (written by heart, not tested):
$('#1 :input').val('');
But this wouldn't restore previously set default values. Or I must store all default values beforehand and I have to check for textareas, inputs, checkboxes etc … Is there another way of doing this?
Not sure if this is what you meant, but this will filter all fieldsets which do not have an id of two and then reset the form elements within those fieldsets to their default values (please note that defaultValue will only work for input/textareas!):
$(document).ready(function() {
$('#btn-reset').on('click', function(e) {
e.preventDefault();
$('form > fieldset').filter(function() {
return $(this).prop('id') !== 'two';
}).children(':input').each(function() {
$(this).val(this.defaultValue);
});
});
});
example markup
<form>
<fieldset id="one">
<input type="text" value="this is a default value" />
<textarea>this is another default value</textarea>
<p>this paragraph doesn't get looped over</p>
</fieldset>
<fieldset id="two">
<input type="text" value="text here.." />
<textarea>hello world!</textarea>
</fieldset>
<button id="btn-reset">Reset</button>
</form>
Here's a fiddle
Change all of the values, then click reset, all of the values in the first fieldset will be reset to their default values, whilst the second set will remain untouched.
There is no way of doing this without JavaScript... The reset button will always reset the whole form element.
Hope this will solve your problem
http://www.electrictoolbox.com/jquery-clear-form/
You can do this using KnockoutJS. Create a view model with default values.