Naming of input elements in a dynamically created form - javascript

I am very new to Javascript, so sorry if I don't use the correct terminology.
I have a form that can dynamically grow. In other words I have buttons that will add labels and input fields to whenever the user clicks it.
At the end of the form, I'd like to have some "done" button that runs another JavaScript function.
However I notice that all of the input fields have the same id (since the function makes the id the same each time).
What is the correct way to access these variables???
Below is the function to dynamically create the fields.
I havent written the function to use the form yet.
function buildDefaultFields(){
// Define container
var chargeItem_container = document.getElementById("chargeItem_container");
// INPUT Start Date
chargeItem_container.appendChild(document.createTextNode('Start Date: '));
var startDate = document.createElement("input");
startDate.type = 'date';
startDate.name = 'startDate';
startDate.id = 'startDate';
chargeItem_container.appendChild(startDate);
chargeItem_container.appendChild(document.createElement("br"));
}

Don't use an id if its not going to uniquely identify a single element, instead use a class
startDate.className = 'startDate';
then use getElementsByClassName to retrieve them
var elements = document.getElementsByClassName ('startDate');// then loop through the elements

You should dynamically add the elements such that each element gets a new id. You could use a simple counter to append to your id names.
For example, if you keep a global var count = 0, then your first id could be 'startDate-' + count which will be startDate-0, then perform an increment on count, so that the next time you add an element, it will get the id 'startDate-' + count = startDate-1.
Hope that helps.

Related

how to make input null after submiting?

hello I made a to do list app and I want to clear input after submit here is my code but it doesn't workenter image description here
I expect input section to be null after I submit but every time I have to use backspace then write a new task
First, I would change class="myinput" to id="myinput".
You are assigning user_input to the value of the input at that moment.
Replace your code line to get value by id:
let user_input=document.getElementById("myinput");
let user_input_value=user_input.value;
compare: if(user_input_value!='')
clear with: user_input.value='';
Hi
You just need to save the input element in a variable and set the value property to empty string rather than directly setting user_input = ''.
Also, unless there many inputs you need to loop through, it's better to use id and document.getElementById to identify the input you want rather than document.querySelectorAll
Save the input element as const
const user_input = document.getElementById('myInputId');
// get the value and use as needed
let user_input_value = user_input.value;
After, when you need to reset, set the input elements value to ''
user_input.value = '';

Overwrite html div class element

I'm trying to add a duplicate element with a different class name as javascript won't add a duplicate object.
Expectations -
I added a button with an event listener on to grab the parent element html and change the class of it but it changes the class of old element as well.
Goal is to get a duplicated element in form if someone got multiple phone no. with button you should get an another input option
Here's my code for, doesn't work as i told
add_button.addEventListener('click', e=>{
const data = e.target.parentElement.parentElement
// Grabs the parent element on height 2
console.log(data) // Got the expected data
// ran_value = Math.floor((Math.random() * 100000) + 1); // Tried this function to generate a random value for class
var data_new = data // Created another instance of data
data_new.setAttribute('class', '1') //add class name
console.log(data_new) // changes the class name
// paramsDiv.appendChild(data)
});
Here's my result which I am getting
While in expected result, it should have changed the class name or added it in 2nd div only so duplicate div element can be appended into form paramsDiv.
Expected result is ->
Donot assign with var data_new = data instead clone the node with var data_new = data.cloneNode(true) Reference
Assigning the dom object to a new variable will not create a new independent copy. Instead both variables will point to same location.
If you want to insert the element as the first child, you can make use of Node.insertBefore()
Reference
Working Fiddle
const add_button = document.getElementById('add-button');
add_button.addEventListener('click', e => {
const data = e.target.parentElement.parentElement
// Grabs the parent element on height 2
console.log(data) // Got the expected data
// ran_value = Math.floor((Math.random() * 100000) + 1); // Tried this function to generate a random value for class
var data_new = data.cloneNode(true); // Created another clone instance of data
data_new.setAttribute('class', '1') //add class name
console.log(data_new) // changes the class name
// paramsDiv.appendChild(data)
});
<div>
Content
<button id="add-button">Add</button>
</div>
The reason it happens is because when you assign data to new_data, you are not creating a new object. You are simply telling new_data to point at data. For that reason, when you change new_data, data changes aswell. In order to create a completely new element, try this:
var data_new = data.cloneNode(true);
I don't know exactly your code but you could try to use nodeClone(), see the documentation: https://developer.mozilla.org/fr/docs/Web/API/Node/cloneNode
because the problem you have here is probably the "referencing".
Tell me how it goes.

Google Scripts - keep track of element [duplicate]

Update: This is a better way of asking the following question.
Is there an Id like attribute for an Element in a Document which I can use to reach that element at a later time. Let's say I inserted a paragraph to a document as follows:
var myParagraph = 'This should be highlighted when user clicks a button';
body.insertParagraph(0, myParagraph);
Then the user inserts another one at the beginning manually (i.e. by typing or pasting). Now the childIndex of my paragraph changes to 1 from 0. I want to reach that paragraph at a later time and highlight it. But because of the insertion, the childIndex is not valid anymore. There is no Id like attribute for Element interface or any type implementing that. CahceService and PropertiesService only accepts String data, so I can't store myParagraphas an Object.
Do you guys have any idea to achieve what I want?
Thanks,
Old version of the same question (Optional Read):
Imagine that user selects a word and presses the highlight button of my add-on. Then she does the same thing for several more words. Then she edits the document in a way that the start end end indexes of those highlighted words change.
At this point she presses the remove highlighting button. My add-on should disable highlighting on all previously selected words. The problem is that I don't want to scan the entire document and find any highlighted text. I just want direct access to those that previously selected.
Is there a way to do that? I tried caching selected elements. But when I get them back from the cache, I get TypeError: Cannot find function insertText in object Text. error. It seems like the type of the object or something changes in between cache.put() and cache.get().
var elements = selection.getSelectedElements();
for (var i = 0; i < elements.length; ++i) {
if (elements[i].isPartial()) {
Logger.log('partial');
var element = elements[i].getElement().asText();
var cache = CacheService.getDocumentCache();
cache.put('element', element);
var startIndex = elements[i].getStartOffset();
var endIndex = elements[i].getEndOffsetInclusive();
}
// ...
}
When I get back the element I get TypeError: Cannot find function insertText in object Text. error.
var cache = CacheService.getDocumentCache();
cache.get('text').insertText(0, ':)');
I hope I can clearly explained what I want to achieve.
One direct way is to add a bookmark, which is not dependent on subsequent document changes. It has a disadvantage: a bookmark is visible for everyone...
More interesting way is to add a named range with a unique name. Sample code is below:
function setNamedParagraph() {
var doc = DocumentApp.getActiveDocument();
// Suppose you want to remember namely the third paragraph (currently)
var par = doc.getBody().getParagraphs()[2];
Logger.log(par.getText());
var rng = doc.newRange().addElement(par);
doc.addNamedRange("My Unique Paragraph", rng);
}
function getParagraphByName() {
var doc = DocumentApp.getActiveDocument();
var rng = doc.getNamedRanges("My Unique Paragraph")[0];
if (rng) {
var par = rng.getRange().getRangeElements()[0].getElement().asParagraph();
Logger.log(par.getText());
} else {
Logger.log("Deleted!");
}
}
The first function "marks" the third paragraph as named range. The second one takes this paragraph by the range name despite subsequent document changes. Really here we need to consider the exception, when our "unique paragraph" was deleted.
Not sure if cache is the best approach. Cache is volatile, so it might happen that the cached value doesn't exist anymore. Probably PropertiesService is a better choice.

Adding a value to a dynamically created element and then having that value pass to another html page when that element is clicked

The elements are created in a for loop. I have tried storing each element ID in an array but it and using it but its always set to the last value the for loop ran through. Tried solving this problem with closures and still nothing works.
Heres a function I have after for loop, with i being passed in each time. moreinfolink is an empty array initialised outside the for loop. idarr is another array with different values in, which I want to reference using the moreinfolink array. Essentially when each element is clicked, the id it has based on its position in the moreinfolink should be used to then get its relevant position in the idarr, which are passed on to another page. And that pages content is genered using an API, for which we need the correct id (found in the idarr). Hope Im making sense.
function passthrough (a){
moreinfolink[a] = document.createElement("a");
moreinfolink[a].id = a;
newmoreinfo.appendChild(moreinfolink[a]); /* element I created elsewhere */
moreinfolink[a].innerHTML = "ID position in array is " + moreinfolink[a].id;
moreinfolink[a].href = "respage.html";
moreinfolink[a].onclick = moreinfo(idarr, moreinfolink[a].id); }
Both the overall array of returned ids (idarr) and each links relevant reference id (moreinfolink[a]) is passed into this function below upon the click event. Problem is that the last id is always passed through, so no matter which link you click it always passes through the last id the loop ended with instead of the one that should be assigned to that particular element.
function moreinfo (relarr, val) {
var carryover = [];
carryover.push(val);
window.name = carryover;
console.log("carryover is " + carryover)}
The function below is called when the other page is opened.
function generateapage () {console.log(window.name);}
You can add query stirng to href:
moreinfolink[a].href = `/respage&id=${moreinfolink[a].id}`;
Then you can read it when other pages load:
let id = new URLSearchParams(window.location.search).get('id')

How can I update the background color of a dynamic input control?

I'm successfully creating some dynamic input textboxes using the following javascript:
var type = "Textbox";
var foo = document.getElementById("fooBar");
for (i = 1; i <= totalQty; i = i + 1) {
var textbox = document.createElement("input");
//Assign different attributes to the element.
textbox.setAttribute("type", type + i);
//textbox.setAttribute("value", type + i);
textbox.setAttribute("name", type + i);
textbox.setAttribute("id", type + i);
textbox.setAttribute("style", "width:300px");
textbox.setAttribute("width", "300px");
//Append the element in page (in span).
var newline = document.createElement("br");
foo.appendChild(newline);
foo.appendChild(textbox);
}
Everything works fine with that. Once the user keys in data and clicks submit however, I need to go back and set the background-color of any textboxes with an error to red. I found some code to do the actual coloring:
textbox.style.backgroundColor = "#fa6767";
...and I know the exact name of the textbox with the error (i.e. "Textbox1", "Textbox2", "Textbox3", etc) but I'm not sure how to programatically assign this background color code to the specific textbox. I can't use something like this, since all code is dynamically generated:
errorTextbox = $("#Textbox1");
Any suggestions?
It looks like you're building a form validation script. Here's an easier way to do this:
1) Create an entry in your stlyesheet for your error class. Adding and removing a class requires fewer steps than assigning properties individually.
.error {
background-color: #ff0000;
}
2) Give all the textboxes you wish to validate a unique class name "valMe", for example.
3) Then loop through them during the validation step:
$('.valMe').each(function() {
$(this).removeClass('error');
if($(this).text=='') {
$(this).addClass('error');
}
})
By using "this" you refer to the current element, so you don't even need to know the ID of the element.
If you already know the name (in this case identical to the id) of the element, you can use jQuery to select the element by forming the selector using string concatenation. Assuming you have a variable that stores the name/id of the text box that has the error, then it's a relatively simple process:
var errorTextboxName = 'Textbox1';
$('#' + errorTextboxName).css('background-color', 'red');
I ended up going with the following:
document.getElementById('Textbox1'.style.backgroundColor = "#fa6767";
I originally didn't think I would be able to capture my "Textbox1" control in this fashion since when I viewed the html source code, there was no "Textbox1" due to the fact I dynamically created it.
Thanks.

Categories

Resources