After searching a lot on Stackoverflow, I couldn't find a solution where only Javascript used code was achieving to do the task that I wanted to create.
I have a form created on React where I am generating input fields with the help of add and remove buttons. On the other hand, what I want is based on the user input on the field, there will be other inputs as well. To clarify more let's take a look at the example picture below to draw the frontend profile:
When the user enters the quantity of products, new fields will be automatically generated based on the input value without the need for clicking any button. For example if the quantity is 5, I need 5 input fields for that product as in the image below
I want to achieve this using Javascript functions but since I am a beginner, I don't know what to use or apply. I would appreciate a lot for your advises and solutions. Cheers!
My answer is not strictly a component but it shows more or less how you can deal with a confined structure (package) capturing the input
event listener for all the quantity input text controls.
Every time the event fires (when the user inputs data inside the field), the given number of "products" are created and added to the corresponding element in the package where the event originated.
Styling wise it's terrible but I did the bare minimum to deliver something worth seeing.
I styled the product number in the list using css counters
and a ::before
pseudo element just for the sake of adding maybe useful ideas to the game:
//add input event listener to qty input
[...document.querySelectorAll('.package .qty')]
.forEach( qtyEl => {
qtyEl.addEventListener('input', (event)=>{
const qtyEl = event.target;
const qty = event.target.value;
clearProducts(qtyEl);
addProducts(qtyEl, qty);
});
})
//removes the products in the given package
function clearProducts(from){
const target = from.closest('.package').querySelector('.products');
target.innerHTML = '';
}
//adds a number of products in the given package
function addProducts(from, n){
const target = from.closest('.package').querySelector('.products');
for(let i = 0; i<n; i++){
const product = createProduct();
target.append(product);
}
}
//creates and returns a product
function createProduct(){
const product = document.createElement('div');
const input = document.createElement('input');
product.classList.add('product');
input.classList.add('product-name');
product.append(input);
return product;
}
.package{
display: flex;
flex-wrap: wrap;
gap: 1em;
border: solid purple;
padding: 1em;
margin-bottom: 1em;
counter-reset: product;
}
.package .type{
width: 50%;
height: 2rem;
}
.package .products{
width: 100%;
display: flex;
flex-direction: column;
padding: 1em;
}
.product{
position: relative;
margin-bottom: 1em;
border: solid 1px darkgray;
padding: 1em;
}
.product::before {
counter-increment: product;
position: absolute;
content: "Product " counter(product) ": ";
top: -13px;
left: 10px;
font-size: 1rem;
color: darkgray;
background: white;
padding: 2px;
}
.product input{
width: 100%;
border: none;
}
<div class="package">
<input type="text" class="type">
<input type="number" class="qty">
<div class="products">
</div>
</div>
<div class="package">
<input type="text" class="type">
<input type="number" class="qty">
<div class="products">
</div>
</div>