jQueryUI - Adding-removing buttons dynamically from a jQueryUI dialog

It was a rather interesting situation. I needed to add/remove buttons dynamically from a jQueryUI dialog that had already been rendered. Based on user interaction, I either needed to add new buttons or remove existing ones.

I checked the jQueryUI docs and there was nothing in the library that seemed to provide a similar functionality for manipualting dialog buttons after the dialog had been rendered (here's where I find ExtJs superior to jQuery/jQueryUI combination, it could be my personal opinion but when it comes to serious javascript development with highly complex UIs, nothing beats ExtJs).

Anyways, a naive approach would have been to simply close the existing dialog and show a new one with the desired buttons. However as can be imagined, this would not have been too user-friendly and would have lead to an irritating flicker on the screen that might have confused the user.

A quick look at a jQueryUI dialog button's dom revealed that it was a simple <span> wrapped inside a <div> element with various classes applied. So, my first approach was to simply append another <div> tag which had exactly the same classes and structure as a jQueryUI button, something like the following:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }var buttonEl = jQuery('#dialog-element').parent().find('.ui-dialog-buttonset'); var id = 'btn-' + new Date().valueOf().toString(); buttonEl.append('<button id=' + id + ' type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false"><span class="ui-button-text">Another</span></button>'); jQuery('#' + id).click(function() { alert('Dynamically added button was clicked.'); });{/syntaxhighlighter}

I am assuming "dialog-element" here to be the unique id of the html element which was used to create the jQuery UI dialog. Each jQuery UI dialog has a <div> section with the class "ui-dialog-buttonset" applied which acts as the container for all buttons for that dialog. So, I manually appended a <div> to that container button <div> with buttons classes, and voila, the new dynamic button was there.

It worked perfectly, with only a minor issue, things like mouse-over effects did not worked with this approach. So, I thought there must be a better way to approach this. After some playing around, I came up with the following code:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }var buttonEl = jQuery('#dialog-element').parent().find('.ui-dialog-buttonset'); var id = 'btn-' + new Date().valueOf().toString(); buttonEl.append('<span class="ui-button-text dynamic-button" id="' + id + '">Click Me!</span>'); jQuery('#' + id).button().click(function() { alert('Dynamically added button was clicked.'); });{/syntaxhighlighter}

And this made the dynamically added button function exactly like as if the button was specified in the original dialog configuration, with mouse-over effects and everything else you would expect from a jQuery UI dialog button.

In this approach, instead of adding a <div> tag with the button classes, I insert a <span> tag with just the button text and then create a Button object for that <span> tag (jQuery(id).button()). This means that jQuery UI adds all the functionality for the button to our span tag. Hmmm... it was easy in the end than I had anticipated.

You can see the example of the same below. Try clicking "Add Button" multiple times and then click "Remove Buttons".

Additionally just as a proof of concept, the example below also demonstrates manipulating content of an already rendered jQuery UI dialog. As you can see from the code below, manipulating dialog content happens normally as you would manipulate the content of dom using jQuery.

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }{ text: 'Append Content', click: function() { sampleDialog.append('<h3>Here\'s dynamically added content.</h3>'); } }, { text: 'Remove select', click: function() { jQuery('#select1').remove(); } }, { text: 'Add Button', click: function() { var buttonEl = sampleDialog.parent().find('.ui-dialog-buttonset'); var id = 'btn-' + new Date().valueOf().toString(); buttonEl.append('<span class="ui-button-text dynamic-button" id="' + id + '">Click Me!</span>'); jQuery('#' + id).button().click(function() { alert('Dynamically added button was clicked.'); }); } }, { text: 'Remove Buttons', click: function() { jQuery('.dynamic-button').remove(); } }{/syntaxhighlighter}

 

The complete code for producing the above example is attached below.

AttachmentSize
HTML icon jquery-ui-dynamic-button.htm2.1 KB

Comments

Creating dynamic clickable objects had me foxed for some time too. I couldn’t get the delegate() function to work either. Eventually I found this example and modified it to:

var buttonClear = $('#formResult').parent().find('#formMessage');
buttonClear.append("<input type='button' value='Clear message' id='clear'>");
$("#clear").click(function() {
            // do button click action here
});

The formResult is a form id already on the page and the formMessage is a dynamically added message displayed after the form is submitted. The script adds a button to the end of the form to clear the message.

Thank you