SharePoint Modal Dialog from HTML

The problem

The SharePoint SP.UI.ModalDialog namespace enables you to open a Modal Dialog by specifiying either a URL to load inside the dialog, either a string continaing the HTML to display in the dialog.

 

Wait… the second option won't work.

 

What the documentation says about the html parameter is: "A string that contains the HTML of the page that appears in the dialog".

 

So the following piece of code should open a modal dialog with the "Hello world" mention:

 

var options = SP.UI.$create_DialogOptions();
options.title = "My Dialog Title";
options.width = 600;
options.height = 400;
options.html = '<div>Hello World</div>';


SP.UI.ModalDialog.showModalDialog(options);

 

 

In fact it won't do anything. No error and no dialog. I think you will agree that the documentation is wrong on this point. The html parameter is not a string containing HTML, it is a DOM Element that will be displayed in the Modal Dialog. And you know what? That makes sense. Specifying an HTML string would have been restrictive especially when dealing with events.

 

Here is a full working version of our "Hello world" example:

 

<div id="DialogContent">Hello World</div>
	
<input type="button" onclick="openHelloDialog();" value="Open Dialog"/>
	
<script type="text/javascript">
	
	function openHelloDialog() {
		var options = SP.UI.$create_DialogOptions();
		options.title = "My Dialog Title";
		options.width = 600;
		options.height = 400;
		options.html = document.getElementById('DialogContent');

		SP.UI.ModalDialog.showModalDialog(options);
	}
	

</script>

 

Nice!!! Wait a minute… You should see two drawbacks in this solution:

  • The content of the dialog is displayed before opening the dialog
  • It works only one time. The dialog cannot be opened multiple times without refreshing the page.

The first point could be easily forgotten, it's easy to hide the element on the parent page with a "display: none" and remove it after opening the dialog.
The second problem is a lot more interesting because it gives us a clue about the Modal Dialog's mecanism. When the dialog is opened the DOM Element specified by the HTML parameter is not copied. The element is nothing more than removed from its parent container, then added to the dialog content.

 

Cool isn't it?

 

The solution

One solution would be to create the DOM elements in memory with document.createElement but that's painful and not easy to maintain. My solution is the following:

  • Put the markup of the dialog into a script block which won't be rendered or interpreted by the browser thanks to a type="text/html" attribute
  • Create a DOM Element in memory with jQuery with the markup specified in the script block
  • Attaching events in memory thanks to jQuery
  • Opening the Modal Dialog with the DOM Element created in memory

Here is a working example:

 

<script type="text/html" id="DialogMarkup">
	<div>
		<label for="FirstNameTextBox">First Name :</label>
		<input type="text" id="FirstNameTextBox"/>
		<input type="button" id="SubmitButton" value="Submit"/>
	</div>
</script>

<input type="button" onclick="openDialog();" value="Open Dialog"/>

<script type="text/javascript">

	function openDialog() {
		var options = SP.UI.$create_DialogOptions();
		options.title = "About you";
		options.width = 400;
		options.height = 250;
		options.html = createDialogElement();
		options.dialogReturnValueCallback = dialogCallback;

		SP.UI.ModalDialog.showModalDialog(options);
	}
	
	function createDialogElement() {
		
		var dialogElement = $($('#DialogMarkup').html());
		dialogElement.find('#SubmitButton').on('click', function() {
			SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK,  $('#FirstNameTextBox').val());
		});
		
		return dialogElement.get(0);
	}
	
	function dialogCallback(dialogResult, returnValue) {
		
		if(dialogResult == SP.UI.DialogResult.OK && returnValue) {
			alert('Welcome ' + returnValue);
		}
	}

</script>

 

 

Note : your script block MUST contain only ONE root element. The jQuery call $($('#DialogMarkup').html()) will take all the nodes of the markup block into account but the statement "return dialogElement.get(0)" returns only the first one. That's the reason why I put a single div around my controls.

 

The final result is very simple. When you click on the "Open Dialog" button a SharePoint Modal Dialog is opened and displays a text box. When you click on the "Submit" button after entering content into the text box, the dialog is closed and your text is displayed by the opening page.

Comments (2) -

http://dotnetfollower.com
http://dotnetfollower.com
9/19/2012 2:16:33 PM #

Hello!
Thank you for a very useful article. A few questions.

Will it work if we define the javascript right inside the SubmitButton? Something like this

<script type="text/html" id="DialogMarkup">
    <div>
        <label for="FirstNameTextBox">First Name :</label>
        <input type="text" id="FirstNameTextBox"/>
        <input type="button" id="SubmitButton" value="Submit" onclick="javascript:SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK,  $('#FirstNameTextBox').val());" />
    </div>
</script>

It looks more convinient for maintanace.

And question about <script type="text/html"... Does it work for all browsers? Probably it makes sense to use traditional style="display:none" plus span? Like this

<span id="DialogMarkup" style="display:none">
...
</span>

Benjamin
Benjamin
9/20/2012 7:15:29 PM #

Hi,
Yes you can put your callback into the onclick of the Submit button. Personnaly I prefer to attach JavaScript events with the jQuery bind / on / live functions than the onclick attribute because they enable you to attach multiple events. It's more powerful.

And yes a script block with text/html is legal. If you check the valid values of the type attribute you will see that it accepts any MIME/Type.
Knockout.js (a great MVVM JavaScript implementation) works with this type of block. I get the idea from this project Smile

Of course it works with a container with a display:none.

Add comment

biuquote
  • Comment
  • Preview
Loading

About me

After sudying at SUPINFO Indian Ocean and SUPINFO Montreal I am now Analyst Programmer at Ivanhoe Cambridge. 

Month List