0

I am trying to build a UI drag and drop builder. My problem so far is that when I add and row or duplication a row, I am not allowed to add columns within the new appended row. How can I solve this issue to allow duplicated or appended rows to then add columns within that row?

$('.add_or_delete button').click(function() {
  if ($(this).text() == 'Add Row') {
    $(this).parent().parent().append('<div class="row"><div class="col"></div><div class="add_or_delete"><button>Add Column</button><button>Delete Column</button></div></div>');
    make_DragDrop();
  }
  if ($(this).text() == 'Add Column') {
    $(this).parent().parent().append('<div class="col"></div>');
    make_DragDrop();
  }
});

function make_DragDrop() {
  $(".row, #columns").sortable({
    placeholder: "ui-state-highlight",
    forcePlaceholderSize: true,
    connectWith: ".connectedSortable",
  });
  $(".row").disableSelection();
}
make_DragDrop();
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="builder_container">
  <div class="element_picker">
    <div class="select_layouts">
      <ul class="connectedSortable" id="columns">
        <li class="col">1</li>
        <li class="col">2</li>
        <li class="col">3</li>
        <li class="col">4</li>
      </ul>
    </div>
  </div>
  <div class="builder_canvas">
    <div class="canvas_container">
      <div class="section">
        <div class="add_or_delete">
          <button>Add Row</button>
          <button>Delete Row</button>
        </div>
        <div class="row connectedSortable">
          <div class="add_or_delete">
            <button>Add Column</button>
            <button>Delete Column</button>
          </div>
          <div class="col">1</div>
          <div class="col">2</div>
        </div>
      </div>
    </div>
  </div>
</div>
Twisty
  • 30,304
  • 2
  • 26
  • 45
  • https://jsfiddle.net/mohamedyousef1980/ho307wme/ you need [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Mohamed-Yousef Jun 10 '17 at 01:37
  • What is the difference between event binding and the functions I have so far?@Mohamed-Yousef – Henzly Meghie Jun 10 '17 at 10:10

1 Answers1

0

As @Mohamed-Yousef mentioned, you have to bind a click event callback to a new dynamically created element. You can do this in a few ways. I tried using .on() method and that didn't seem to work to well for this, so I went a little more manual.

Test Example: https://jsfiddle.net/Twisty/8fmd1zbc/

$(function() {
  $(".add_or_delete .add-row-btn").click(addRow);
  $(".add_or_delete .add-col-btn").click(addCol);

  function addRow(e) {
    console.log("Adding Row.");
    var newRow = $("<div>", {
      class: "row"
    });
    newRow.append($("<div>", {
      class: "add_or_delete"
    }).append($("<button>", {
      class: "add-col-btn"
    }).html("Add Column").click(addCol), $("<button>", {
      class: "del-col-btn"
    }).html("Delete Column").click()), $("<div>", {
      class: "col"
    }).html("&nbsp;"));
    $(e.target).parents(".section").append(newRow);
    make_DragDrop();
  }

  function addCol(e) {
    console.log("Adding Col.");
    $(e.target).parents(".row").append('<div class="col">&nbsp;</div>');
    make_DragDrop();
  }

  function make_DragDrop() {
    $(".row, #columns").sortable({
      placeholder: "ui-state-highlight",
      forcePlaceholderSize: true,
      connectWith: ".connectedSortable",
    });
    $(".row").disableSelection();
  }

  make_DragDrop();
});
.row {
  border: 1px dashed blue;
  margin: 1em;
}

.row .add_or_delete {
  padding: .2em .4em;
}

.col {
  border: 1px dotted red;
  display: inline-block;
  margin-top: -1px;
  margin-left: -1px;
  width: 100%;
}
<link href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="builder_container">
  <div class="element_picker">
    <div class="select_layouts">
      <ul class="connectedSortable" id="columns">
        <li class="col">1</li>
        <li class="col">2</li>
        <li class="col">3</li>
        <li class="col">4</li>
      </ul>
    </div>
  </div>
  <div class="builder_canvas">
    <div class="canvas_container">
      <div class="section">
        <div class="add_or_delete">
          <button class="add-row-btn">Add Row</button>
          <button class="del-row-btn">Delete Row</button>
        </div>
        <div class="row connectedSortable">
          <div class="add_or_delete">
            <button class="add-col-btn">Add Column</button>
            <button class="del-col-btn">Delete Column</button>
          </div>
          <div class="col">1</div>
          <div class="col">2</div>
        </div>
      </div>
    </div>
  </div>
</div>

You can see how I bind a new click event callback to each button when I add it. Since I will not now how many buttons exists, I make relative paths based on the e.target or the event target, the element that was clicked. Using .parents() saves me a little code since it will traverse till it finds that parent selector.

I can see you're early in your development of this project and would strongly advise adding more proper classes and id attributes to your elements. It seems like more work up front and it will save you a lot of time later. It's a good practice and it makes altering or changing your code further down the line a lot easier since selecting or confirming an element becomes a lot easier.

Twisty
  • 30,304
  • 2
  • 26
  • 45