Freigeben über


How to – SharePoint 2010 – JS client object model and UI advancements

This blog entry shows how to utilize the new UI functionalities available in the SharePoint 2010 and how to use JavaScript object model to manipulate the site structure.

Create initial structure in VS2010

The first step is to create the Visual Studio solution. In this case we will create a new Empty SharePoint project with name ClientOMUIActions.

image

Since we will be adding Visual Web Part to the project, we will need to use the farm solution option.

 image

The following step is to add a new Visual Web Part item to the project – let’s name it UIDemo

 image 

Add dialog integration

In this case we need to add the dialog framework integration code to our visual web part, we can definitely use the same model in ribbon buttons, if required. Let’s add the following script element to the Visual Web Part canvas.

<script type="text/javascript">

   //Dialog opening
   function OpenDialog() {
        var options = SP.UI.$create_DialogOptions();
        options.url = "/_layouts/ClientOMUIActions/ListCreationPage.aspx";
        options.width = 500;
        options.height = 400;
        options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);
        SP.UI.ModalDialog.showModalDialog(options);
    }

    var messageId;

    // Dialog callback
   function CloseCallback(result, target) {
        if(result === SP.UI.DialogResult.OK) {
            alert("OK was clicked!");
        }
        if(result === SP.UI.DialogResult.cancel) {
            alert("Cancel was clicked!");        
        }
    }

 </script>

Here are a few things from the code worth pointing out

  • Notice the url property, which is set for the DialogOptions. This is the target url to be shown in the dialog. In this case we point to the custom application page, which we will create in upcoming steps
  • Notice also how to set the delegate for call back. In this case we define that when ever the dialog is closed, CloseCallback function will be called
  • Notice how we check the return value usign SP.UI.DialogResult and act upon the response
  • messageId variable will be used later, so let’s add it now but use it later

The following step is to hook up JavaScript to our link, so let’s add the following to the Visual Web Part canvas as well so that when ever the the link is clicked, our dialog code is invoked.

<br /> <a href="Javascript:OpenDialog();">Start UI and client om demo</a>

Let’s test the functionality by deploying the web part to the portal and clicking the link. We should see following popup opened up.

image

This error is due the fact that we haven’t implemented our dialog page yet. Let’s close the dialog by clicking the close button from the top right corner. You should see the following alert window shown.

image

Modify application page

The following step is to create and modify the application page to use little bit nicer UI. We also need to add some code to provide response value correctly back to the parent window. Let’s add a new application page to our project named ListCreationPage.aspx.

 image

Since we want to use the SharePoint style of rending of the dialog content, let’s add the following registration line on the top of the page, just above the Page statement. We will be using the controls to provide a nice SharePoint like popup “feeling”.

<%@ Register Tagprefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register TagPrefix="wssuc" TagName="InputFormSection" src="/_controltemplates/InputFormSection.ascx" %>

<%@ Register TagPrefix="wssuc" TagName="InputFormControl" src="/_controltemplates/InputFormControl.ascx" %>

<%@ Register TagPrefix="wssuc" TagName="ButtonSection" src="/_controltemplates/ButtonSection.ascx" %>

Following step is to add the required JavaScript to handle the call back functionality. Let’s add following script elements to PlaceHolderAdditionalPageHead content place holder.

<script type="text/javascript">

function BtnCreateListCancel_Click() {

       SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 
                                                                        'Cancelled clicked');

    }

    function BtnCreateListOk_Click() {

        var form = document.forms.<%SPHttpUtility.NoEncode(Form.ClientID,Response.Output);%>;

        var ListNameUrl = form.<%SPHttpUtility.NoEncode(TxtListName.ClientID,Response.Output);%>.value;

        SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, ListNameUrl);

    }

</script>

I’ll point out a few of the elements from the code

  • We create two separate functions – one for the OK click event and one for the Cancel event.
  • Notice how to pass the DialogResult enumerator value based on our response
  • In the OK function, we also take the value from existing textbox on the page, which is passed as a parameter to commonModalDialogClose function

Following step is to create the actual page layout. You’ll need to add following to the place holder called PlaceHolderMain.

<table

     id="maintable"

     border="0"

     cellspacing="0"

     cellpadding="0"

     class="ms-propertysheet"

     width="100%"

>

<wssuc:InputFormSection Title="List name" runat="server">

<Template_Description>

<SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server"

                                       text="Define list name to be created."EncodeMethod='HtmlEncode'/>

</Template_Description>

<Template_InputFormControls>

<wssuc:InputFormControl runat="server">

<Template_Control>

<table border="0" cellspacing="1">

<tr>

<td class="ms-authoringcontrols" colspan="2" nowrap="nowrap">

<SharePoint:EncodedLiteral ID="EncodedLiteral7" runat="server"

                   text="List name will be used as url and as the title"

                   EncodeMethod='HtmlEncode'/>:

                    <font size="3">&#160;</font><br />

</td>

</tr>

<tr>

<td dir="ltr">

<table>

<tr>

<tdnowrap="nowrap"colspan="2"class="ms-authoringcontrols">

<wssawc:InputFormTextBox title="Enter list name" class="ms-input" ID="TxtListName" Columns="35" Runat="server" maxlength="255" size="60" width="100%" />

</td>

</tr>

</table>

</td>

</tr>

</table>

</Template_Control>

</wssuc:InputFormControl>

</Template_InputFormControls>

</wssuc:InputFormSection>

<wssuc:ButtonSection runat="server" ShowStandardCancelButton="False">

<Template_Buttons>

<asp:placeholder ID="Placeholder1" runat="server">

<inputclass="ms-ButtonHeightWidth" type="button " name="BtnCancel" id="Button1"

                           value="OK" onclick="BtnCreateListOk_Click()" />

<SeparatorHtml>

<span id="idSpace" class="ms-SpaceBetButtons" />

</SeparatorHtml>

<input class="ms-ButtonHeightWidth" type="button" name="BtnCancel" id="Button2"

                            value="Cancel" onclick="BtnCreateListCancel_Click()" />
</asp:PlaceHolder>

</Template_Buttons>

</wssuc:ButtonSection>

</table>

Few pointers again on the code to clarify what we just did

  • We use the InputFormControl and InputFormSection controls to provide a nice look and feel for our popup
  • In this case the buttons are html buttons, since we are not using code behind code to do anything in this case
  • Notice how we call the JavaScript functions we created in the previous step from the button clicks

Now that the dialog page has been implemented, let’s test the functionality. You should get following dialog.

image 

Now if you click OK, you should see following alert shown – this confirms that our dialog callback is working properly.

image

Add notifications

Let’s start using the notifications, to replace the “ugly” alerts, which we are currently using. SharePoint 2010 provides a really nice notification framework, which we can easily utilize. Let’s update the CloseCallback function on the visual web part as follows.

// Dialog callback

function CloseCallback(result, target) {

    if (result == SP.UI.DialogResult.OK) {

        //Get id

        messageId = SP.UI.Notify.addNotification("<img src='_layouts/images/loading.gif'> Creating list <b>" + target + "</b>...", true, "Dialog response", null);

        //Create list using client OM

        //createList(target);

    }

    if (result == SP.UI.DialogResult.cancel) {

        SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null);

    }

}

Again here’s a few things to point out from the code

  • We use the SP.UI.Notify.addNotification function to notify the end user based on the action in the dialog.
  • Notice how we also use the callback value in the message (target parameter) – in this case we are showing the list name to be created
  • We can use html for the notifications – in this case we added a small gif animation in the OK button click
  • Creating list – message is shown using sticky mode (second parameter on the function call) and we store the notification identifier, so that we can show the message until the the list has been actually created
  • Notice the commented CreateList function call – we’ll add this in following step

Now if you try the functionality again, you should get following messages shown on the user interface, depending on the button you clicked.

image  image

Add JavaScript client object model code

Objective was to create new list using Client object model when ever OK is clicked. Since the JavaScript OM is by default available in any SharePoint page, we can just add the following functions.

//Actual JS client side object model calls

function createList(listName) {

    //Create client context.

    var clientContext = new SP.ClientContext();

    var oWebsite = clientContext.get_web();

    //Let's create list creation information object

    var listCreationInfo = new SP.ListCreationInformation();

    listCreationInfo.set_title(listName);

    listCreationInfo.set_templateType(SP.ListTemplateType.announcements);

    listCreationInfo.set_quickLaunchOption(SP.QuickLaunchOptions.on);

    this.oList = oWebsite.get_lists().add(listCreationInfo);

    //Let's create also new item to the list to be created

    var itemCreateInfo = new SP.ListItemCreationInformation();

    this.oListItem = oList.addItem(itemCreateInfo);

    oListItem.set_item('Title', 'Example item for ' + listName);

    oListItem.set_item('Body', 'Hello seminar audience. From list ' + listName);

    oListItem.update();

    clientContext.load(oListItem);

    clientContext.load(oList);

    //Execute the actual script

    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));

}

//Called if client side OM is successful

function onQuerySucceeded() {

    //Remove the 'creating' event notification

    SP.UI.Notify.removeNotification(messageId);

    //Add 'created' notification as non sticky

    SP.UI.Notify.addNotification("List <b>" + oList.get_title() + "</b> created...", false, "", null);

}

function onQueryFailed(sender, args) {

    //Remove the 'creating' event notification

    SP.UI.Notify.removeNotification(messageId);

    //Shown in case of error on the JS OM call

    SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null);

}

Remember also to uncomment the createList call from the CloseCallback function

//Create list using client OM

createList(target);

Here’s a few things again from the code

  • Notice how we first get the client context, before we start doing anything
  • The executeQueryAsync method call actually invokes our modifications on server side from the JavaScript – we set two different function callbacks here, depending on the result. During this call, the requested actions are sent to the server side handler for manipulation
  • In both callback functions we remove the previously added sticky notification, before adding new one to indicate the result

If the changes have been applied properly and you now test the dialog functionality, after providing the list name and clicking OK, you should get following message after a while.

image

If you navigate to All Site Settings, you can see that the new list with single example item has been created.

image

Dialog framework and code behind code in dialogs

In the example we just went through, we used only client side code, but it’s quite common that you’ll need to execute also server side OM code as part of the dialog operations. In that case after you have executed any server side code, you can execute the following code to close the dialog and return results back to caller window.

//Close the dialog - we are good to go

this.Page.Response.Clear();

this.Page.Response.Write(string.Format(CultureInfo.InvariantCulture,

     "<script type=\"text/javascript\">window.frameElement.

commonModalDialogClose(1, '{0}');</script>", ListItems.Count));

this.Page.Response.End();

Notice following from the code

  • Two different parameters are passed to the commonModalDialogClose JavaScript function
  • First one defines the response code – in this case it’s 1, which means success (same as SP.UI.DialogResult.OK). You can also return 0, which would mean cancel
  • Second parameter can be used to pass any relevant information for your application. In this case we return the count of items in the ListItems variable, which we utilized in our server side code.

Summary

As I wrote in the beginning of this blog entry, we can definitely use similar code and approach also from ribbon buttons, which makes extending of the ribbon extremely easy. SharePoint 2010 provides excellent web 2.0 platform for developers. For more information about the new capabilities, check MSDN.

Hopefully this was useful – btw. Due miscellaneous reasons, the full package won’t be unfortunately available at least for a while…

Comments

  • Anonymous
    March 17, 2010
    Oah, Amazing article, I have learned a lot from here Thank you so much

  • Anonymous
    March 18, 2010
    The comment has been removed

  • Anonymous
    March 19, 2010
    Hi, thanks for the feedback and the improvement suggestion. That really helps to make demo more straight forward. .vesku

  • Anonymous
    March 22, 2010
    Good article.  A question about the OK/Cancel buttons though: It looks like you included your own.  I would expect a dialog framework to provide those in a standard way, and just allow you to indicate the type of dialog you want (OK, OK/Cancel, etc).  I'd rather not worry about localizing those strings. Also, you include a reference to ButtonSection.ascx.  It doesn't seem to work for me (I get a compiler warning, and nothing shows up at run time) - any ideas?

  • Anonymous
    March 22, 2010
    I was making a dumb mistake, and got the ButtonSection to work now.  It still gives compiler warnings though, so I'd be curious how to resolve those.

  • Anonymous
    March 25, 2010
    The comment has been removed

  • Anonymous
    April 13, 2010
    The CloseCallback function doesn't get called when using this to delete a list item.

  • Anonymous
    May 28, 2010
    Great article! The ButtonSection doensn't work because of the asp:PlaceHolder tags don't start with correct case.

  • Anonymous
    June 02, 2010
    Great article. One query is ,how can we use localize the  title of dialog window. I know the title is pssed through the dialog options.How can we use of the satellite assemblies in javascript?

  • Anonymous
    August 22, 2010
    I think this code will only work for Root Site Collection

  • Anonymous
    August 22, 2010
    Hi Sandeep, that's correct. This is reference example and with the current code, it only works in the root site collection due the URL mapping to aspx file is using the following format - "options.url = "/_layouts/ClientOMUIActions/ListCreationPage.aspx" - so we are always linking to root site collection in the dialog opening. You could easily provide dynamically the url based on the context you are. Key point is to have the above link to be created dynamically using server SPContext.Site etc.

  • Anonymous
    August 27, 2010
    Here a good link that provide details about the Model Dialog of Share Point 2010 www.a2zmenu.com/.../SharePoint%202010%20Model%20Dialog.aspx

  • Anonymous
    October 27, 2010
    Unfortunately, I can't  use your code. Because after calling the dialog, I'm getting the mistake - "The server tag is not well formed". I have cut the your code (In placeholder - PlaceHolderMain:) for the next view: <table     id="maintable"     border="0"     cellspacing="0"     cellpadding="0"     class="ms-propertysheet"     width="100%"    >      <wssuc:InputFormSection Title="List name" runat="server">          <SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server"                                       text="Define list name to be created."EncodeMethod='HtmlEncode'/>       </wssuc:InputFormSection>       </table> I think the truble is in calling  - wssuc:InputFormSection, because VS2010 make a next warning on it - "Element 'InputFormSection' is not a known element. This can occur if there is a compilation error in the Web site, or the web.config file is missing". All registration operations you wrote I've maid. The top of my dialog page look as follows: <%@ Register Tagprefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register TagPrefix="wssuc" TagName="InputFormSection" src="/_controltemplates/InputFormSection.ascx" %> <%@ Register TagPrefix="wssuc" TagName="InputFormControl" src="/_controltemplates/InputFormControl.ascx" %> <%@ Register TagPrefix="wssuc" TagName="ButtonSection" src="/_controltemplates/ButtonSection.ascx" %> <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="mydialog.aspx.cs" Inherits="modaldialog2.Layouts.modaldialog2.mydialog" DynamicMasterPageFile="~masterurl/default.master" %> I would appreciate if you will show me my mistake.

  • Anonymous
    December 16, 2010
    Hi Vesa. I have the same issues as Anton.  I am getting the error message "Element InputForm is not a known element.'  and also if I go ahead and deploy the page I get Parser Error - "Parser Error Message: System.Web.UI.WebControls.TableRowCollection must have items of type 'System.Web.UI.WebControls.TableRow'. 'wssuc:InputFormSection' is of type 'ASP._controltemplates_inputformsection_ascx'." What step am I missing?  Please help. Thanks.

  • Anonymous
    January 01, 2011
    I couldn't get this to work as I was getting the same issue. I reworked the <table> as follows: <table     id="maintable"     border="0"     cellspacing="0"     cellpadding="0"     class="ms-propertysheet"     width="100%"    >      <wssuc:InputFormSection Title="List name" runat="server">       <Template_Description>          <SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server"                                       text="Define list name to be created." EncodeMethod='HtmlEncode'/>        </Template_Description>        <Template_InputFormControls>          <wssuc:InputFormControl runat="server">            <Template_Control>              <table border="0" cellspacing="1">                <tr>                  <td class="ms-authoringcontrols" colspan="2" nowrap="nowrap">                    <SharePoint:EncodedLiteral ID="EncodedLiteral7" runat="server"                   text="List name will be used as url and as the title"                   EncodeMethod='HtmlEncode'/>:                    <font size="3"> </font><br />                  </td>                </tr>                <tr>                  <td dir="ltr">                  <table>                      <tr>                          <td nowrap="nowrap" colspan="2" class="ms-authoringcontrols">                            <SharePoint:InputFormTextBox title="Enter list name" class="ms-input" name="txtListName" ID="TxtListName" Columns="35" Runat="server" maxlength="255" size="60" width="100%" />                          </td>                      </tr>                  </table>                  </td>                </tr>              </table>            </Template_Control>          </wssuc:InputFormControl>        </Template_InputFormControls>      </wssuc:InputFormSection>       <wssuc:ButtonSection runat="server" ShowStandardCancelButton="False">        <Template_Buttons>          <asp:placeholder ID="Placeholder2" runat="server">          <input class="ms-ButtonHeightWidth" type="button" name="BtnOk" id="Button1"                            value="OK" onclick="BtnCreateListOk_Click()" />                      </asp:PlaceHolder>           <SeparatorHtml>                <span id="idSpace" class="ms-SpaceBetButtons" />            </SeparatorHtml>          <asp:placeholder ID="Placeholder1" runat="server">          <input class="ms-ButtonHeightWidth" type="button" name="BtnCancel" id="Button2"                            value="Cancel" onclick="BtnCreateListCancel_Click()" />                      </asp:PlaceHolder>        </Template_Buttons>      </wssuc:ButtonSection>      </table>

  • Anonymous
    January 13, 2011
    Nice Article

  • Anonymous
    February 05, 2011
    Hi, Is this possible to resize the model at runtime. i.e. attached a file after that a  modal of 800*800 is this possible????

  • Anonymous
    March 31, 2011
    The comment has been removed

  • Anonymous
    May 23, 2011
    Great Stuff!!! I was struggling to close the dialog after executing server side code. Thanks.

  • Anonymous
    July 28, 2011
    How can i make this from af c# codebehind file ??

  • Anonymous
    July 29, 2011
    Hi "Help", Popup works onlly in JavaScript mode, if your request is to open up the popup immediately when someone arrives on the page... this means that you should be just writing proper JavaScript entries to html and make sure that it's automatically called during page load. There's no way directly starting client side script (JavaScript) from code, which is running in server (code behind), but this can be achived by rendering required JavaScript to html for telling client side browser to open up the popup immediately when page is loaded.

  • Anonymous
    October 08, 2011
    I have used commitPopup() to close dialog. praveenbattula.blogspot.com/.../close-sharepoint-2010-dialog-through.html

  • Anonymous
    October 12, 2011
    nice post  good information the way of wriiten appriciated sharepointsolution2010.blogspot.com/.../sharepoint-2010-dialog-close-using-code.html

  • Anonymous
    November 24, 2012
    Nice post. Informations are helpful. I have around 50 popups in my application. To make it more generic; i have created custom framework for popups. This framework can load any .net user control & handle ok, cancel button event to call sharepoint list or sql DB. I have used this blog basics to create my custom framework sharepoint.infoyen.com/.../sharepoint-2010-popup-dialogs. Thank you very for your blog. Avinash

  • Anonymous
    September 24, 2013
    thanks