Passing the result from a dialog to the parent page

Sometimes you want to communicate with the parent page of your dialog in order to pass on the result of your work. Thankfully the SP.UI.ModalDialog framework contains the commonModalDialogClose method. The javascript CSOM has all the tools in place to construct the following application:

  • Add a button to the ribbon. This button will also open the dialog.
  • Create an application page that will be used as a dialog. This application page has a text box and a button.
  • Add javascript to capture the result of the application page, in this case just text, and put it where our cursor resides on the parent page.

First things first, we’ll add a button to our ribbon.

ribbonbutton

Since there are many tutorials available, I won’t go into detail here. Simply add an empty element to your project and replace the contents with this one:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
    Id="bramnuyts.InsertButton"
    Location="CommandUI.Ribbon"
    Title="InsertRibbon Button">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition
          Location="Ribbon.EditingTools.CPInsert.Groups._children">
          <Group
            Id="Ribbon.EditingTools.CPInsert.InsertGroup"
            Sequence="1"
            Description="Insert"
            Title="Insert"
            Template="Ribbon.Templates.Flexible2"
            >
            <Controls Id="Ribbon.EditingTools.CPInsert.InsertGroup.Controls">
              <Button Id="Ribbon.EditingTools.CPInsert.InsertGroup.InsertButton"
                Command="InsertCommand"
                Image16by16="/_layouts/images/removeStylesHS.png"
                Image32by32="/_layouts/images/removeStylesHH.png"
                LabelText="Insert"
                TemplateAlias="o2" />
            </Controls>
          </Group>
        </CommandUIDefinition>
        <CommandUIDefinition
          Location="Ribbon.EditingTools.CPInsert.Scaling._children">
          <MaxSize
            Id="Ribbon.EditingTools.CPInsert.InsertGroup.MaxSize"
            Sequence="15"
            GroupId="Ribbon.EditingTools.CPInsert.InsertGroup"
            Size="LargeLarge" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
          Command="InsertCommand"
          CommandAction="javascript:insert();" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
  <CustomAction
    Id="InsertCommand.Script"
    Location="ScriptLink"
    ScriptSrc ="/_layouts/DialogResult/insert.js" />
</Elements>

I added the javascript in a separate javascript file “insert.js”. I like the ScriptLink approach as it doesn’t dirty the elements.xml file. However there are some reported issues when using ScriptLinks so go for the approach you feel is the most safe.

insert.js

Inside my insert.js file I have 2 methods: addElement(txt) and insert(). The “insert()” method will be responsible for handling the click on the button and creating the dialog. The “addElement(txt)” method will be responsible for adding content to the rich content page. Once again SharePoint is there to help us, this time it’s the “RTE” class, which points to the Rich Text Editor. By using the “RTE.Cursor.get_range()” method, we’re able to determine where a user has put his cursor.

function addElement(txt) {
    var range = RTE.Cursor.get_range();
    range.deleteContent();
    var selection = range.parentElement();
    if (!selection) {
        return;
    }
    var span = selection.ownerDocument.createElement('span');
    span.innerText = txt;
    range.insertNode(span);
    RTE.Cursor.get_range().moveToNode(span);
    RTE.Cursor.update();
}

function insert() {
    var options = {
        url: SP.Utilities.Utility.getLayoutsPageUrl('/DialogResult/insert.aspx'),
        title: 'Insert',
        allowMaximize: false,
        showClose: true,
        width: 300,
        height: 150,
        dialogReturnValueCallback: Function.createDelegate(null, function (result, returnValue) {
            if (result == SP.UI.DialogResult.OK) {
                    addElement(returnValue);
            }
        })
    };

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

Now that we have our button and the javascript to handle the dialog, we have to create our dialog page.

insert.aspx

I added a text box and a button to the main contentplaceholder:

insert.aspx.main

Add the “Button1_Click” OnClick method to the button and add the following code to the code behind:

protected void Button1_Click(object sender, EventArgs e)
{
    int result = 1; // Result = OK
    string returnValue = TextBox1.Text;
    Page.Response.Clear();
    Page.Response.Write(String.Format(
        CultureInfo.InvariantCulture, 
        "<script type=\"text/javascript\">window.frameElement.commonModalDialogClose({0}, {1});</script>", 
        new object[] { 
            result, 
            String.IsNullOrEmpty(returnValue) ? "null" : String.Format("\"{0}\"", returnValue) 
        }));
    Page.Response.End();
}

The code will close the dialog window, pass “OK” as result and text from the text box as return value.

When you deploy the code (make sure that your package contains the button) you’ll see the following button appear when you edit your rich content page:

result ribbon

When you click the button the dialog page will appear:

result dialog

When you insert some “test text” and click insert, your text will show up where you left your cursor:

result test text

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s