Correct Way to Dynamically Add Semantic UI Controls?

Adam Haile picture Adam Haile · May 29, 2015 · Viewed 9.2k times · Source

I'm trying to wrap my head around Semantic UI and I understand how everything is controlled by what class you give to a DOM element, but I can't really get that to work when adding new DOM elements dynamically. It seems like the semantic ui javascript is only getting run on first page load and not on those new elements when I add them. Currently, this is just done via:

$("#target").html("<new elements here>")

Is there are correct way to do this? I cannot find any documentation about this on the Semantic UI site.

Update: To give a better example...

Say I have this layout:

<div class="right menu" id="rightMenu">
    <div class="ui dropdown link item">
      Courses
      <i class="dropdown icon"></i>
      <div class="menu">
        <a class="item">Petting</a>
        <a class="item">Feeding</a>
        <a class="item">Mind Reading</a>
      </div>
    </div>
    <a class="item">Library</a>
    <a class="item">Community</a>
  </div>
</div>

And this code is run:

var menu = '<div class="ui dropdown link item"> \
  Test \
  <i class="dropdown icon"></i> \
  <div class="menu"> \
    <a class="item" href="http://google.com">Google</a> \
    <a class="item" href="http://amazon.com">Amazon</a> \
  </div> \
</div>';

$("#rightMenu").append(menu)

The new menu item appears just fine... BUT it doesn't actually dropdown like it should, until I run this:

$('.ui.dropdown')
  .dropdown({
    on: 'hover'
  });

After that, it opens on hover just fine. But is there a way to not have to rerun that every time?

Answer

lshettyl picture lshettyl · May 29, 2015

There are few ways of adding elements to DOM. html (would empty the container and then insert new elements) is one of them. You can also use append to append new elements to an existing set. But, your problem is about events not being triggered on dynamically added elements. The solution for this is event delegation. Read more about it here.

From the jQuery doc: Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers.

Here is a quick demo I'd set up about adding new elements, event delagation etc. Hope that helps.

var $container = $("#container");
var count = 3;

$container.on("click", 'button', function() {

    alert ("You've clicked on " + $(this).text() );
});

$("#addButtons").on("click", function() {

    $container.append("<button>Button" + (++count) + "</button>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
    <button>Button1</button>
    <button>Button2</button>
    <button>Button3</button>
</div>

<button id="addButtons">Add a few more!</button>

EDIT: Even for dynamically adding Semantic UI elements, the rule remains the same as it's just an element. I am not sure if there are other problems on your page. Look at the updated demos below.

1) Using append

2) Using html

EDIT: So, that's how the Semantic UI Dropdown is supposed to work as the dropdown is created/rendered by Javascript. Therefore, when new options/dropdowns are added the related method ($('.ui.dropdown').dropdown({on: 'hover'});) needs to be re-triggered. Another workaround is to add the simple class to the newly created dropdown, i.e. var menu = '<div class="ui simple dropdown link item"> \ which would trigger the dropdown when you mouseover, but. it's with no animation!

Hope that helps.