A jQuery Library for SharePoint Web Services (WSS 3.0 and MOSS): Real World Example – Part 1

Cross posted from EndUserSharePoint.com

Part 1 Part 2 Part 3 Part 4

So I’ve been going on about how wonderful this jQuery Library for SharePoint Web Services stuff is, but you may have wondered if I ever actually use the library in real world situations. You bet I do, and it lets me build some pretty nice solutions fast. (Writing this article may have taken longer than implementing the jQuery bits on the form I describe below!)

Here’s a real world example from a current client project. In this example, we’ve got a repository for artifacts which come out of the software development lifecycle (SDLC). Of course, this is a pretty standard idea, but this client takes it a bit further in that they have a well thought out set of required artifacts based on the project’s methodology and project type. So we’ve got a set of lists that we use relationally in a bunch of Data View Web Parts (DVWPs) to display the projects with clear indications of how the Project Manager is doing against the artifact requirements in a dashboard-y way.

The first part of all of this is to be sure that we set up the projects cleanly. In this case, there are Projects and Requests. (Think of Requests as sub-projects.) The form below shows how we set up a new Request.

The first thing we want to ensure is that the RequestID is unique; we don’t want to accidentally add a Request to the list a second time. Here, we’re using the SPRequireUnique function, which allows us to enforce uniqueness in any Single line of text column. The function call looks like this:

$().SPServices.SPRequireUnique({
	columnStaticName: "Title",
	duplicateAction: 1,
	ignoreCase: "false",
	initMsg: "The RequestID must be unique.",
	errMsg: "This RequestID already exists."
});

The StaticName for the RequestID column is Title – we’ve just repurposed the standard, required Title column. In duplicateAction, we can specify 1, meaning that we will prevent the user from submitting a duplicate value item, or 0, which simply warns the user if there is a duplicate value. If you look at the screenshot, the OK button is disabled because the current value is not unique. Note that we can also customize the messages which the user sees in the form with the initMsg and errMsg options.

Because Requests are related to Projects, we have a Lookup column in the Requests list which takes its values from the ProjectID in the Projects list. Of course, that ProjectID is just a nonsensical code which doesn’t really mean anything to anyone. Along comes SPDisplayRelatedInfo to the rescue. By showing a few key column values for the Project, we can make sure that the user knows that they have chosen the right ProjectID.

$().SPServices.SPDisplayRelatedInfo({
	columnName: "ProjectID",
	relatedList: "SDLC Projects",
	relatedListColumn: "Title",
	relatedColumns: ["Project_x0020_Name", "Methodology",
		"Business_x0020_Group"],
	displayFormat: "list"
});

Finally, due to the volume of artifacts that the repository needs to support, we’re creating a folder for each Request. I am NOT a fan of folders, but there are times when they make sense. In this instance, we already have over 5000 artifacts in the repository, and it is just going to continue to grow. By putting each Request’s artifacts into a unique folder, we can be sure of two things:

  • We won’t exceed the magical, mystical 2000 item limit per list container (the list root or any single folder)
  • We can avoid naming collisions. Because we have multiple Project Managers contributing artifacts and we have no way of knowing what they will name their documents, we want to be sure that a document titled Project Plan for one Request doesn’t overwrite a Project Plan for another request.

So, on commit of the new Request item, we use the Lists Web Service UpdateListItems operation to create a new folder to contain the artifacts for this Request. SharePoint provides us with a nice little stub function called PreSaveAction that we can use to check on things when we save an item. If that function exists in the form, SharePoint will call it before the commit. If the function returns true, then everything is A-OK. If it returns false, SharePoint won’t commit the item. Here we’re creating the new folder in the PreSaveAction:

function PreSaveAction() {
	var requestId = $().find("input:[Title='RequestID']").val();
	$().SPServices({
		operation: "UpdateListItems",
		async: false,
		listName: "SDLC Repository",
		updates: "<Batch OnError='Continue' PreCalc='TRUE'>" +
				"<Method ID='1' Cmd='New'>" +
					"<Field Name='FSObjType'>1</Field>" +
					"<Field Name='BaseName'>" + RequestId + "</Field>" +
				"</Method>" +
			"</Batch>",
		completefunc: function(xData, Status) {
			…
		}
	});
	return true;
}

I’m glossing over the error handling here with the ellipses. We’re going to assume that the folder is created and just move along.

So, tying it all together, we can make all this happen by simply adding the script to our form. We don’t need to customize the List Form Web Part (LFWP) on the form in any way. The first step is to take a copy of NewForm.aspx in SharePoint Designer; I generally call it NewFormCustom.aspx. We do this because we don’t ever want to destroy the default form. We may need to go back to it, and there’s no way to recreate it manually if it’s gone.

Then I edit NewFormCustom.aspx and add the script into the page. I’m showing the PlaceHolderMain line because I put my script block immediately below that existing line; I don’t add it. The first two lines are the references to the core jQuery library and the jQuery Library for SharePoint Web Services, respectively. Then we wrap the SPRequireUnique and SPDisplayRelatedInfo functions in the $(document).ready(function() so that they run once the page is fully loaded.

<strong><asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<script type="text/javascript" language="javascript" src="../../JavaScript/jquery-1.3.2.min.js"></script>
<script type="text/javascript" language="javascript" src="../../JavaScript/jquery.SPServices-0.4.6.js"></script>
<script type="text/javascript">

$(document).ready(function() {
	$().SPServices.SPRequireUnique({
		columnStaticName: "Title",
		duplicateAction: 1,
		ignoreCase: "false",
		initMsg: "The RequestID must be unique.",
		errMsg: "This RequestID already exists."
	});
	$().SPServices.SPDisplayRelatedInfo({
		columnName: "ProjectID",
		relatedList: "SDLC Projects",
		relatedListColumn: "Title",
		relatedColumns: ["Project_x0020_Name", "Methodology",
			"Business_x0020_Group"],
		displayFormat: "list"
	});
});

function PreSaveAction() {
	var requestId = $().find("input:[Title='RequestID']").val();
	$().SPServices({
		operation: "UpdateListItems",
		async: false,
		listName: "SDLC Repository",
		updates: "<Batch OnError='Continue' PreCalc='TRUE'>" +
				"<Method ID='1' Cmd='New'>" +
					"<Field Name='FSObjType'>1</Field>" +
					"<Field Name='BaseName'>" + RequestId + "</Field>" +
				"</Method>" +
			"</Batch>",
		completefunc: function(xData, Status) {
			…
		}
	});
	return true;
}
  </script>

The final step is to set NewFormCustom.aspx as the form for creating new items. To do this, you right click on the list in the Folder View, choose Properties, and then click on the Supporting Files tab. (The screenshot below is for a different list, but you’ll get the picture.) Be sure to choose the right Content Type in the Content type specific forms dropdown. Generally this just means NOT to select Folder.

Browse to NewFormCustom.aspx, click OK, and you’re good to go!

In the next articles, I’ll cover some of the Data View Web Parts (DVWPs) I’ve built to show the Project Managers their current status against the artifact requirements and a nifty bulk upload enhancement that lets them upload multiple documents and tag them with metadata in a single step.

7 Comments

  1. Hello, this post is great. But it won’t work in my Edit Form. I wanna use this solution in a library. So i added the code on my Edit Form with a CEWP. But the only message i saw was the “his value must be unique” although the values of the column aren’t unique. I didn’t get the “red message”. What did i do wrong? Hope someone give me a advice.

    Reply

Have a thought or opinion?