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…