1,804 articles and 15,211 comments as of Sunday, April 17th, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint (Joel Oleson) content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Monday, November 23, 2009

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

Marc D AndersonGuest Author: Marc D. Anderson
http://mdasblog.wordpress.com

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.


Real World Example

Real World ExampleThe 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.

Real World ExampleBecause 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"
});

Real World ExampleFinally, 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.

Real World Example

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.

Marc D AndersonGuest Author: Marc D. Anderson
http://mdasblog.wordpress.com

Marc D. Anderson is a Co-Founder and the President of Sympraxis Consulting LLC, based in Newton, MA.  He has over 25 years of experience as a technology consultant and line manager across a wide spectrum of industries and organizational sizes.  Marc has done extensive consulting on knowledge management and collaboration and what makes them actually work in practice.  Marc is a very frequent “answerer” on the MSDN SharePoint – Design and Customization forum.

 

Please Join the Discussion

12 Responses to “A jQuery Library for SharePoint Web Services (WSS 3.0 and MOSS): Real World Example – Part 1”
  1. tom says:

    This is one of the better articles I’ve seen on this site to improve business functionality, thanks for sharing!

  2. Jeremy Thake says:

    Great post Marc, getting more and more convinced with jQuery. I have been tackling this by deploying these as Custom Field Controls with self contained jQuery in the .ascx files.
    Your approach is to use SharePoint Designer and modify the form pages? How will this affect upgrades to #SP2010 UI?

  3. Jeremy:

    That’s a good question re: upgrades to SP2010. I haven’t fired it up yet, as you probably know. Want to test it for me? :+)

    M.

  4. Joel Smith says:

    Hi Mark,

    I have begun experimenting with the library, it is great, the potential fantastic.

    I am having some problem with using the SPDisplayRelatedInfo function with a relatedListColumn is an ID. I get the error “Column not found in related list”.

    Has this been encountered before?

    Thanks again for an excellent resource.

  5. Joel:

    Let’s move this one over to the Codexplex site Discussions, OK? http://spservices.codeplex.com/Thread/List.aspx

    Can you post some more details there so that I can try to reproduce the issue? In the meantime, I’ll try to see if I can trigger the bug in my test environment.

    M.

  6. Nirav says:

    Hi,
    I just started experimenting . I want to update the list. This is not updating items when site is viewed in Sharepoint. works fine when opened in IE.

    I used same code block “PreSaveAction” of this example,just changed the list name and updating Title field only of other list.

  7. Nirav says:

    Just spell mistake. not working when site is viewed in FireFox

  8. Nirav:

    Let’s move this over to the Codeplex site as well in case it’s a bug I need to track. Can you please post more details here http://spservices.codeplex.com/Thread/List.aspx?

    Thanks,
    M.

  9. Brian Bedard says:

    If you want to be upgradeable, you can’t use Designer. Also you can’t use designer if you want to make this a deployable solution in a feature using a list schema.
    I recommend using RenderingTemplates. These puppies are the templating mechanism SharePoint uses to create the ListFormWebParts. There’s no swapping out of default forms either. You can have your cake and eat it too.
    It would be very easy to copy the “ListForm” RendingTemplate and drop in references to your javascript functions like jQuery for SharePoint Web Services. The key is when creating the list schema to specify the XmlDocuments node in the ContentType declaration. I have a blog post explaining how this mechanism works. It’s a fascinating mechanism.

  10. Brian:

    I took a look when you menntioned RenderingTemplates on Twitter. They are definitely cool, but they require touching the server and custom coding. My goal with this library is to require nothing on the back end and to be entirely client side. Different strokes for different folks.

    As I mentioned in Twitter, I thoroughly expect that some of the functions in my library will:
    * No longer be necessary in SP2010 because the functionality exists natively.
    * Need retooling due to differences in the DOM, Web Services, etc.
    In the meantime (and I expect the meantime to last for quite a while), folks are solving real business challenges relatively easily and quickly. Goodness!

    M.

Trackbacks

Check out what others are saying about this post...
  1. [...] had a question on my recent article over at EndUserSharePoint.com entitled A jQuery Library for SharePoint Web Services (WSS 3.0 and MOSS): Real World Example – Part 1.  The question was about the SPDisplayRelatedInfo function, and while I was setting things up [...]




Notify me of comments to this article: