<p>Type in the text boxes, click and check console</p>
<button id='addDiv'>Add Div</button>
<div id='container'></div>
.row {
  display: flex;
  margin: .5rem 0;
}

.row button {
  margin-left: 1rem;
}


const rowTemplate = function(count) {
  return `
    <div id='row-${count}' class='row'>
      <div>
          <label for='textDescription-${count}'>
          <input type='text' id='textDescription-${count}'>
      </div>
      <div>
          <button id="btn-${count}" data-for='textDescription-${count}'>Click me</button>
      </div>
    </div>
`
}

const getAddRowHandler = function(container) {
  
  let count = 0
  
  // return handler
  // both count and container will be scoped inside the handler's closure
  return function(event) {
    container.insertAdjacentHTML('beforeend', rowTemplate(count++))
  }
}

const rowClickHandler = function(event) {
  
  // event.target = what we clicked on
  const target = event.target
  // if it isn't a button return early
  if (!target.matches('button')) return
  
  // traverse from the button element up to the nearest .row class e.g. it's row container
  const row = target.closest('.row')
  // data-for or in JS the button's dataset.for holds the id to the textbox
  const textBox = row.querySelector(`#${target.dataset.for}`)
  // As a test console.log contents of text box.
  console.log(textBox.value)
}

const addRowButton = document.querySelector('#addDiv')
const container = document.querySelector('#container')

// pass the container element to the getAddRowHandler and get back the handler function
addRowButton.addEventListener('click', getAddRowHandler(container))

// Like Paul I am using event delegation and letting the events bubble up
container.addEventListener('click', rowClickHandler)
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.