Dynamic Redirect Using SPRedirectWithID

Coordinator
Jan 8, 2010 at 6:27 PM

Marc,

I'm trying to 're-purpose' your redirect with ID function to achieve some slightly different behavior with forms. I want to be able to send the user to different URL's based on the value of a select box. A good example being if you submit an item as "current" you'll be sent to the view of all the current items; if you submit an item as "archive" you'll be sent to the view for all archived items. This is in an effort to improve the user interaction a bit for a particular tool I'm working on.

I've got my PreSaveAction() function as below, but on form submission I'm seeing the NewForm.aspx file reload with the ID and a RealSource parameter. I'm not seeing the Source that I defined anywhere. Is there somewhere else that I need to tell it to actually complete the redirect? I think this is a useful secondary way to use your function, though my implementation may be flawed.

<script type="text/javascript" src="../../js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="../../js/jquery.SPServices-0.4.7.min.js"></script>
<script type="text/javascript">
	function getField(fieldType,fieldTitle) {	// LOCATE SHAREPOINT FIELD BASED ON TYPE AND TITLE
	    var docTags = document.getElementsByTagName(fieldType);
	    for (var i=0; i < docTags.length; i++) {
	        if (docTags[i].title == fieldTitle) {
	            return docTags[i]
	        }
	    }
	}
	
	function PreSaveAction() {
		var docstate = getField('select','Document State').value;
		if (docstate == "Released - Current") {
			$().SPServices.SPRedirectWithID({	
				redirectUrl: "SyncProc.aspx"
			});
		}
		return true;
	}
</script>

Coordinator
Jan 8, 2010 at 7:50 PM
Edited Jan 8, 2010 at 11:21 PM

Mike:

I think that I misspoke in my email to you about this now that I'm thinking it through a little more.  What you are doing in PreSaveAction looks fine, but without a call to SPRedirectWithID when the page loads, there's no way for the function to "catch".  Basically what the function does is change the form action to redirect back to the same page after the save with some parameters in the Query String.  When the page reloads, the function "sees" that the Query String parameters (specifically ID) are there and it does the second step of the process, which is waiting for the new item to be committed so that it can grab the ID and pass the user along.

This still might be possible.  If you add a call to SPRedirectWithID into document.ready which is wrapped in a test for the presence of the ID Query String parameter, I think your approach *may* work.

M.

p.s. Since you already have jQuery loaded up, you should be using jQuery selectors in getField!

Coordinator
Jan 12, 2010 at 7:43 PM

I guess the challenge with this is the dynamic redirect combined with getting the ID... each by itself isn't too much of a challenge given the resources at hand, but putting them together seems to be an issue. I'll give you the reason I'm doing it first and then an update of where I am...

In my example above I used views of data because in my mind it was the easiest way to accomplish this. In reality I'm trying to determine when a specific condition exists so I can execute some other web services. I have two lists that store procedure documents, one of which is "public" and the other is only open to a select group of people. The restricted list contains all procedures (archived and current) while the public one must contain all current ones. There is a one-to-many relationship the way the lists are built, so one record may contain multiple attached procedures (hence the use of a list over a document library).

When one of the admins adds a new "Current" procedure (document state set by meta data on the record), I need to run a series of web service calls to accomplish the following tasks:

  • Remove all records of that document ID in the public list
  • Add the record to the public list
  • Determine the attachments on the record, and replicate to the public list

Initially we wanted to do it in a workflow, but workflows don't support attachments (best I can figure out), so I'm resorting to web services which I have had luck with in the past.

I'm not too worried about the three bullets above. I don't think they're outside of the scope of SPServices/jQuery, and we're talking about an action that's going to execute maybe once a week by only one or two people so performance isn't really a worry.

I've tried using "redirectUrl: mySource" and defining mySource in PreSaveAction() but obviously that doesn't work as jQuery initializes before the variable has been populated. I don't have a problem doing the actions in the default newform.aspx, the redirect was just so we had the ability to prompt the user that something was happening--maybe embedding in the form is a better direction.

Coordinator
Jan 12, 2010 at 8:16 PM

Out of curiosity, what permissions do DVWPs need on the list? Their biggest concern is making sure people can't see archived ones. Can a DVWP display data if a user doesn't have access to the source list? Maybe I'm seriously overthinking this...

Coordinator
Jan 12, 2010 at 8:19 PM
Edited Jan 13, 2010 at 1:35 PM

Generally speaking, DVWPs respect the permissions.  There are a few things that may make it look like they don't: expired Announcements, past Events, etc.  Those aren't permission issues, just business rules that the DVWP won't inherit.

My first skim of your post above made me think that you might be overengineering, if only because I realized that I'd need to read it a few more times to reply intelligently!

M.

Coordinator
Jan 13, 2010 at 1:38 PM
Edited Jan 13, 2010 at 1:39 PM

OK, I've read this through a few times again.  I'm not sure why you need to redirect to a page to do the Web Services calls.  Why not just do them in the PreSaveAction?  Or, alternatively, check the Document State when you arrive at the next page?  I guess I'm still a bit confused about what you're trying to do.  Have you thought about having the Public list just contain copies (you can use the Copy Web Service) of the items in the Private list?  Or is that out because you're not using a Document Library?

M.

Coordinator
Jan 13, 2010 at 1:58 PM

I think the copy web service only applies to document libraries, correct?

Doing the call in the presave action might work actually--I was hung up on getting the ID because I thought we'd need it to query back to the other list when the page redirected... let me play with this a tad... more to follow...

Coordinator
Jan 13, 2010 at 3:01 PM

Ok, I like where we're going here now...

Current plan:
PreSaveAction() checks to see if document state is "Released - Current", if it is we'll remove all previous entries from the public list (by procedure ID), then add the form data and attachments to a new record in the public list. The form itself will submit to the archive list.

The only thing I'm not sure how to do is get the attachments out of the stock SharePoint form so I can send them to my public list.

I'm getting an "Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown" message with my UpdateListItems/Delete call; does anything stand out below as being wrong?

if (docState == "Released - Current") {
	$("#PreSaveStatus").html(workingIcon + "Removing previous records.").SPServices({
		operation: "UpdateListItems",
		updates: "<Batch OnError='Continue'>" + 
			"<Method ID='1' Cmd='Delete'>" + 
				"<Field Name='Procedure Identifier'>" + procID + "</Field>" + 
			"</Method>" + 
		"</Batch>",
		completefunc: function (xData, Status) {
			var out = $().SPServices.SPDebugXMLHttpResult({
				node: xData.responseXML
			});
			$("#PreSaveStatus").append(out);
		}
	});
}

Coordinator
Jan 13, 2010 at 3:06 PM

To delete items, you need to pass in the item's ID, so you'll need to use GetListItems first to find all of the items with the 'Procedure Identifier' you're interested in.  You're also not specifying what list in the UpdateListItems call. ;+)

M.

Coordinator
Jan 13, 2010 at 9:28 PM
Edited Jan 13, 2010 at 9:30 PM

Marc,

I'm down to my last hurdle on this project and just wanted to sincerely thank you for your direction. While I still can't believe I asked what was wrong when I hadn't even defined a list... it's been one of those weeks that I just wish would end already. I've been playing catchup on a bunch of random projects and my mind is so frazzled. It's a breath of fresh air to be able to collaborate with someone who appreciates helping others and offers innovative new approaches to things. I think I owe you more than one beer now (don't know if I should tell you to keep track or not, haha).

Coordinator
Jan 13, 2010 at 9:30 PM

No worries! Keep the questions coming, and let me know what you end up with.

Might make a good EUSP article. ;-)

M.

Coordinator
Jan 13, 2010 at 9:32 PM

Yes... if I can get the attachments piece working it might make a great article... I haven't seen much via the Google approach to access the file attachments data from the stock SP form.

Jan 14, 2010 at 8:33 PM

What is the easiest way to do the redirect based on the "title field" instead of the "ID" field. I would like to open the edit form if the "title" field already exists or a new fom of it does not?

Coordinator
Jan 14, 2010 at 10:12 PM

Scott,

In your application I wouldn't use SPRedirectWithID, assuming I'm understanding you correctly.

I'd use an onBlur event to determine when the user leaves the title field. Have that call the GetListItems WS to see if that title exists, and if it does run a window.location to redirect to the edit form. I have some code kicking around that lets you set values through the URL... so you'd just redirect to EditForm.aspx?Title=xxxxx...

If you wanted to, you could probably use Marc's RequireUnique function, but my concern from an end user would be completing the form only to find out I have to do it somewhere else, ie: fill in the form, hit submit, then get redirected to the edit form where half the data I just typed was already there.

Coordinator
Jan 15, 2010 at 4:19 PM

Scott:

Mike's ideas are, as always, good.  It would be interesting to hear more about what you are trying to accomplish.  If you'd like some help, why don't you start a new thread with the details.

M.