Web Application Design (part 1)

Sorry I’ve been away from posting for so long. I’ve been working on a large web application and the design and implementation is taking up a lot of my ‘blogging’ time. But, I use this blog as my notes to remind me how I did certain things, so I need to update it with some new tricks before I completely forget them…

I’ve been adding JavaScript into my projects for a while now, and I’ve started to get a good feel for what I can and can’t do in SharePoint. The following series of tips are very basic and can be accomplished by novice SharePoint designers with ease. If you have any questions, or suggestions to improve my rudimentary code, feel free to post a comment so everyone can learn from the discussions.

The application I am designing requires users to create ‘codes’ for use in drop-down lists. The codes are stored in a custom list which contains only two columns: Code Name (Title) and Active (checkbox). For this series of posts we are going to create a simple list of Customer Statuses. The web application stores Customer Data and the status field in the Customer Data is a lookup to the values in the Customer Status list. The users can therefore add or change codes the drop-down without having to fiddle with SharePoint. The logic used in these examples can be applied to almost any kind of custom list: employee lists, inventory lists, issue tracking lists etc.

I want one page where the user can see the current items in a list, edit the existing items, and create new items in the list. I realise that this can be accomplished by using the DispForm.aspx, NewForm.aspx, and EditForm.aspx but, I want to maintain only one form.

Note: I have started using my own custom masterpage and designing my aspx pages from scratch. I don’t know if these instructions will be affected by placing the forms in an existing SharePoint page, for example – adding a display list to the NewForm.aspx page. I don’t think that it will, but please let me know if it does.

Step One: Display the current contents of the list

Pre-requisite: Create a custom list and populate it with a couple of items.

The primary objective of the page I am creating is to show users the current items in the list, in our example I want to show the users which Customer Status codes already exist in the list. Let’s start by creating a Multiple Item Data View Web Part and place it on the page. I’m pretty sure I’ve covered this in a previous topic but here’s quick recap:

  1. Click anywhere on the page, outside of any existing Web Parts, and insert a Data View.
  2. Click on the Data View and then select the Customer Status list from the datasource library and then click Show Data.
  3. Hold CTRL and select the fields you want to add.
  4. Click on the Insert Selected Fields As button and select Multiple Item View.

The grid (table) will appear on the page and display the contents of the list.

Step Two: Add a an Edit Form

We want the users to be able to click on an item in the grid and be able to edit the item on the same page. Let’s add a Single Item Form Data View.

  1. Locate the end tag for the previous Web Part: </WebPartPages:DataFormWebPart>
  2. Insert a <br /> (to create some space) after the end tag.
  3. Insert a Data View after the <br /> tag.
  4. Click on the Data View and then select the Customer Status list from the datasource library and then click Show Data
  5. Hold CTRL and select the fields the user can edit
  6. Click on the Insert Selected Fields As button and select Single Item Form.

The new form will appear on the page and show the first item in the Customer Status list.

Step Three: Connect the Forms

If you recall, from the previous step, we want the user to be able to click an item in the first grid and have that set the item that can be edited in the edit form. We are going to create a Web Part Connection.

  1.  Right-click a label field, in the edit form we created in Step Two, and select Web Part Connections from the pop-up menu.
  2. When the Web Part Connections Wizard dialog box opens, select Get Parameters From in the drop-down list and click Next.
  3. Verify the radio button for Connect to Web Part on this Page is selected and click Next.
  4. Verify the target Web Part is Customer Status and the target action is Send Row of Data To and click Next.
  5. Click on the Create New Parameter option in the Inputs to Customer Status column.
  6. Name the new parameter “PassedID” and click OK.
  7. Select the ID column from the Columns in Customer Status column in the same row as the PassedID parameter. You are associating the ID column in the display grid with the PassedID parameter in the edit form.
  8. Click Next.
  9. Verify that the Create a Hyperlink On option is set to the Status column.
  10. Select the Indicate Current Selection Using checkbox and select Status from the pop-up list.
  11. Click Next.
  12. Click Finish.

IMPORTANT: I have found a possible bug in SharePoint Designer. In my installation (could just be me), when I have completed the creation of the Web Part Connection sometimes the connection is still not “active”. You can verify the connection was created properly by right-clicking a field in the edit form and selecting Web Part Connections from the pop-up. If the connection was created properly, it will appear in a list. If it was not created properly, the web part connection wizard will launch again. I sometimes find that I have to run the wizard twice (just clicking Next all the way through it the second time) to get the connection to “activate”.

Now that you have the connection established, we need to create a filter on the edit form.

  1. Select the edit form and select Dataview > Filter from the file menu.
  2. Create a filter: ID equals [PassedID]
  3. Click OK

Okay, we now have a grid that shows all of the items in the Customer Status List and if the user clicks on the Status it can be edited in the edit form just below the grid. SharePoint creates a hyperlink on the Status field and highlights the currently selected field.

Step Four: Hyperlink on the Row not the Column

In our current example, the user has to click the Status to change the current item in the edit form. I want to change it so the user can click anywhere in the row and update the edit form. Here is where things get a little scary for beginners. I’m going to try to explain this as clearly as possible because learning this trick is important to gaining control over SharePoint pages.

SharePoint uses HTML tables to structure the layout of the forms and pages. HTML tables always follow the same pattern:

  • The table always begins with the <table> tag and ends with the </table> tag.
  • Each row in the table starts with <tr> and ends with a </tr>. The term “tr” stands for table row.
  • Each column in a row starts with a <td> and ends with a </td>. The term “td” stands for table data cell (I know it’s not very intuitive!!).
  • SharePoint uses XSL to create the table dynamically. SharePoint specifies the value of the first row and the XSL creates as many rows as needed to contain all of the data.

Once we understand these four truths, we can begin to control the way SharePoint behaves (Don’t worry if they seem confusing right now, once we delve into the code it will start to make more sense). If you set the view in SharePoint Designer to SPLIT the screen, you can see the code and the design at the same time. Click on the first Status field in the display form and you can see the code that creates the field. In our example, SharePoint has placed the hyperlink tag <a> inside of the column <td> tag, here’s the code directly from SharePoint (with my comments in red italics):

<tr> (create a row in the table – we’re going to need this tag very soon)
   <xsl:if test=”position() mod 2 = 1″> (everything between the XSL tags is programming stuff)
    <xsl:attribute name=”class”>ms-alternating</xsl:attribute>
   </xsl:if>
   <xsl:if test=”$dvt_1_automode = ‘1’” ddwrt:cf_ignore=”1″>
    <td class=”ms-vb” width=”1%” nowrap=”nowrap”>
     <span ddwrt:amkeyfield=”ID” ddwrt:amkeyvalue=”ddwrt:EscapeDelims(string(@ID))” ddwrt:ammode=”view”></span>
    </td>
   </xsl:if>(end programming stuff)
   <td class=”ms-vb”> (this is the first column the user can see – in our case the Status column)
    <a target=”_self”> (this is the hyperlink we are looking for)
    <xsl:attribute xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” name=”href”>
     <xsl:variable name=”cursel”>dvt_curselkey={
      <xsl:call-template name=”dvt.gencurselkey”>
       <xsl:with-param name=”RowPath” select=”.” />
      </xsl:call-template>
      }</xsl:variable>
     <xsl:variable xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” name=”fields”>@ID=<xsl:value-of select=”ddwrt:ConnEncode(string(@ID))” /></xsl:variable>
     <xsl:text>javascript:</xsl:text>
     <xsl:value-of select=”ddwrt:GenFireConnection(concat(‘g_fed65d2c_6c05_48ed_b84a_0ddc96bdc324*’,$fields),string($cursel))”></xsl:value-of>
    </xsl:attribute>
    <xsl:attribute name=”style”>
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>font-weight: bold;</xsl:if>
    </xsl:attribute>
    <xsl:value-of select=”@Title” />
    </a> (this is the end of the hyperlink tag) </td> (this is the end of the column)
   <td class=”ms-vb”>
    <xsl:choose>
     <xsl:when test=”@Active=’1′ or msxsl:string-compare(string(@Active),’Yes’,”,’i’)=0 or msxsl:string-compare(string(@Active),’True’,”,’i’)=0″>Yes</xsl:when>
     <xsl:otherwise>No</xsl:otherwise>
    </xsl:choose>
   </td>
   </tr> (this is the end of the row)

I want to break the hyperlink code down a little more for you. Here is the contents of the <a> (hyperlink) tag explained in more detail:

<a target=”_self”> (start the hyperlink, but when clicked just reload the current page: target = self)

(This section contains the Web Part Connection Code – very simply put, when I get clicked send the value of the ID field in the current row to the edit form)
<xsl:attribute xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” name=”href”>
     <xsl:variable name=”cursel”>dvt_curselkey={
      <xsl:call-template name=”dvt.gencurselkey”>
       <xsl:with-param name=”RowPath” select=”.” />
      </xsl:call-template>
      }</xsl:variable>
     <xsl:variable xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” name=”fields”>@ID=<xsl:value-of select=”ddwrt:ConnEncode(string(@ID))” /></xsl:variable>
     <xsl:text>javascript:</xsl:text>
     <xsl:value-of select=”ddwrt:GenFireConnection(concat(‘g_fed65d2c_6c05_48ed_b84a_0ddc96bdc324*’,$fields),string($cursel))”></xsl:value-of>
    </xsl:attribute>

(This section contains the highlight code – set the currently clicked item to bold font)
    <xsl:attribute name=”style”>
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>font-weight: bold;</xsl:if>
    </xsl:attribute>

(This is the data field to display)
    <xsl:value-of select=”@Title” />

    </a>(end the hyperlink)

I hope all of that “random” code makes a little more sense now. By recognising the basic tags in the code, we can locate and manipulate individual columns and rows. We wanted to move the <a> tag so that the hyperlink affects the whole row in the grid. The next section of code shows you the altered code and I will highlight what I moved:

<tr>
<a target=”_self”>
    <xsl:attribute xmlns:xsl=”
http://www.w3.org/1999/XSL/Transform” name=”href”>
     <xsl:variable name=”cursel”>dvt_curselkey={
      <xsl:call-template name=”dvt.gencurselkey”>
       <xsl:with-param name=”RowPath” select=”.” />
      </xsl:call-template>
      }</xsl:variable>
     <xsl:variable xmlns:xsl=”
http://www.w3.org/1999/XSL/Transform” name=”fields”>@ID=<xsl:value-of select=”ddwrt:ConnEncode(string(@ID))” /></xsl:variable>
     <xsl:text>javascript:</xsl:text>
     <xsl:value-of select=”ddwrt:GenFireConnection(concat(‘g_fed65d2c_6c05_48ed_b84a_0ddc96bdc324*’,$fields),string($cursel))”></xsl:value-of>
    </xsl:attribute>

   <xsl:if test=”position() mod 2 = 1″>
    <xsl:attribute name=”class”>ms-alternating</xsl:attribute>
   </xsl:if>
   <xsl:if test=”$dvt_1_automode = ‘1’” ddwrt:cf_ignore=”1″>
    <td class=”ms-vb” width=”1%” nowrap=”nowrap”>
     <span ddwrt:amkeyfield=”ID” ddwrt:amkeyvalue=”ddwrt:EscapeDelims(string(@ID))” ddwrt:ammode=”view”></span>
    </td>
   </xsl:if>
   <td class=”ms-vb”>
        <xsl:attribute name=”style”> (we didnt need to move the style code)
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>font-weight: bold;</xsl:if>
    </xsl:attribute>
    <xsl:value-of select=”@Title” />
    </td>
   <td class=”ms-vb”>
    <xsl:choose>
     <xsl:when test=”@Active=’1′ or msxsl:string-compare(string(@Active),’Yes’,”,’i’)=0 or msxsl:string-compare(string(@Active),’True’,”,’i’)=0″>Yes</xsl:when>
     <xsl:otherwise>No</xsl:otherwise>
    </xsl:choose>
   </td>
   <td class=”ms-vb”>
    <xsl:value-of select=”ddwrt:FormatDate(string(@Created), 1033, 5)”/>
   </td>
   <td class=”ms-vb”>
    <xsl:value-of select=”@Author” disable-output-escaping=”yes”/>
   </td></a> (the location of this tag is very important – before the </tr> but AFTER the </td> )
  </tr>
 
As you can see in the example code, I have moved the <a> tag from the inside of the column ( <td> ) to the inside of the row ( <tr> ). If I save and preview this page, I can now click anywhere in the row to change the value in the edit form.

Note: the mouse pointer doesn’t change to reflect the row is a hyperlink but we will correct that in the next step.

Step Five: Change Mouse Pointer on Hover

Changing the mouse pointer when over an item is a very useful JavaScript tip. Users recognise links on a web page from the underline or from the mouse pointer changing when over the link.

If you recall the code I showed you in Step Four, I noted that we would need the <tr> tag. Locate the <tr> tag (the easiest way is to switch to split view and click the first row in the display form). Add the following code to the <tr> tag:

<tr onmouseover=”this.style.cursor=’hand'”>

All I’ve done here is tell the browser to initiate the JavaScript on the row. The JavaScript (onmouseover) activates when the mouse pointer is over the item, in this case the row. The values in the quotes tell the JavaScript to change the cursor (mouse pointer) to the hand. Insert the code in your page and preview the page. When you move the mouse over a row in the display form, it will change to a ‘hand’ cursor and your user knows that they can click there.

As you might have already guessed, you can use this little trick in a lot of other situations.

Step Six: Add Some Usability

When I look at the forms we have just created I’m happy with the functionality but, I am not so impressed with the usability. If the list contains 200 items, how do you expect the user to see the little bold highlight on the currently selected row? I want to add some custom code to the forms to improve the usability.

Highlight the Row

There are two types of highlight that I like to use when displaying a grid full of data. If the grid has the edit form on the same page, I want the currently selected row to be highlighted. If the grid links to an edit form on a different page, I want the row to highlight when the mouse pointer moves over it.

In our example, the edit form is on the same page so I want the row to highlight when the user clicks it. If you were paying attention in Step Four, you might have seen that this functionality already exists in a slightly modified format:

    <xsl:attribute name=”style”>
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>font-weight: bold;</xsl:if>
    </xsl:attribute>

The XSL code sets the style on the column when it is the currently selected item. As is, it gives the Status field a tiny little bold affect. Let’s tinker with the code a little:

    <xsl:attribute name=”style”>
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>background-color: #ffffe0;</xsl:if>
    </xsl:attribute>

As you can see, I only changed the style value in the XSL code. The code now sets the background of the selected column to be a nice pale yellow color. You can specify any color you want and you can also change almost any style you want. Here are some examples:

   border: 1px solid red; (set the border of the selected column to red)
   text-decoration: underline; (underline the text in the selected column)

You should experiment with the different combinations of CSS style attributes and values. If you tested and previewed the change, you are probably wondering why only one column is affected. The code for the style is contained with the <td> tag so it affect only the single column. If you copy and paste the style code into each of the columns – it will affect all of the columns. You can’t move the style code up to the row without messing up the web part connection – so for now you have to copy and paste it. Here is the sample code:

<tr>
<a target=”_self”>
    <xsl:attribute xmlns:xsl=”
http://www.w3.org/1999/XSL/Transform” name=”href”>
     <xsl:variable name=”cursel”>dvt_curselkey={
      <xsl:call-template name=”dvt.gencurselkey”>
       <xsl:with-param name=”RowPath” select=”.” />
      </xsl:call-template>
      }</xsl:variable>
     <xsl:variable xmlns:xsl=”
http://www.w3.org/1999/XSL/Transform” name=”fields”>@ID=<xsl:value-of select=”ddwrt:ConnEncode(string(@ID))” /></xsl:variable>
     <xsl:text>javascript:</xsl:text>
     <xsl:value-of select=”ddwrt:GenFireConnection(concat(‘g_fed65d2c_6c05_48ed_b84a_0ddc96bdc324*’,$fields),string($cursel))”></xsl:value-of>
    </xsl:attribute>

   <xsl:if test=”position() mod 2 = 1″>
    <xsl:attribute name=”class”>ms-alternating</xsl:attribute>
   </xsl:if>
   <xsl:if test=”$dvt_1_automode = ‘1’” ddwrt:cf_ignore=”1″>
    <td class=”ms-vb” width=”1%” nowrap=”nowrap”>
     <span ddwrt:amkeyfield=”ID” ddwrt:amkeyvalue=”ddwrt:EscapeDelims(string(@ID))” ddwrt:ammode=”view”></span>
    </td>
   </xsl:if>
   <td class=”ms-vb”>
    <xsl:attribute name=”style”>
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>background-color: #ffffe0;</xsl:if>
    </xsl:attribute>
    <xsl:value-of select=”@Title” />
    </td>
   <td class=”ms-vb”>
   <xsl:attribute name=”style”>
     <xsl:if test=”$CurrentRowKey = $dvt_curselkey”>background-color: #ffffe0;</xsl:if>
    </xsl:attribute>

    <xsl:choose>
     <xsl:when test=”@Active=’1′ or msxsl:string-compare(string(@Active),’Yes’,”,’i’)=0 or msxsl:string-compare(string(@Active),’True’,”,’i’)=0″>Yes</xsl:when>
     <xsl:otherwise>No</xsl:otherwise>
    </xsl:choose>
   </td></a></tr>

In our example, we only have two columns showing. If you have multiple columns, all you need to do is locate the starting tag for each column: <td class=”ms-vb”> and place the style code snippet directly after it.

To sum up, we now have a single aspx page that contains a grid displaying of all of the items in a custom list with an edit form directly below the grid. The user can click anywhere in a row in the grid and the selected row is highlighted and the edit form updates to show the selected item. The user can then edit the item in the edit form and click save and see the changes in the display grid.

In the next part, I will add a New button to the page which will hide the edit form and show a new item form which will allow users to add new items to the display grid from the same aspx page.

Advertisements

June 11, 2008 at 3:42 pm 10 comments

Logging Workflows for Troubleshooting

SharePoint workflows are very powerful tools. SharePoint workflows allow you to automate tasks and workflow processes. If you haven’t used workflows before, I recommend reading the SharePoint online help for workflows:

http://office.microsoft.com/en-us/sharepointdesigner/CH100667661033.aspx

Once you start to use workflows in your SharePoint applications, you realise a very important and fundamental truth; what happens when a workflow fails? By default, you can click on an item in a list and see the workflow history. Unfortunately, the error messages in the workflow can be cryptic to say the least. For example, if I have a workflow that creates new items in 5 different lists and the workflow fails, I get a message saying “Unable to update list item”. The message doesn’t tell me which specific action or step failed or which list it was unable to write to.

To get around this issue, and to provide an even finer level of control over my workflows, I created a custom list and used that list to log my workflow actions. The custom list, called WorkflowLog, contains the following fields:

  • Workflow Name (text field) – stores the name of the workflow that is logging the event.
  • EventOccurred (date & time field) – stores the date and time that the event was completed.
  • Workflow Step (text field) – stores the number and label of the step being completed.
  • Workflow Action (text field) – stores the specific action step completed.
  • Event (multiple line text field) – stores details about the action completed.
  • AdminNotes (multiple line text field) – allows me to store specific notes for troubleshooting.

I configure my workflows to write an entry to the WorkflowLog everytime an important step is completed. If the workflow creates a new item and sets the status to ‘Created’, the next action is to create a new item in the workflow log and log that creation. Here is an example of the line item created by my Auto-increment ClientID workflow:

WorkflowName

AutoAssignClientID 

EventOccurred

5/15/2008 2:03 PM 

WorkflowStep

1 – Update ClientID then Increment ClientID 

WorkflowAction

Updated the ClientID on the new client 

Event

The workflow has taken the latest ClientID from the SystemCounters database and updated the Customer. Then it has incremented the SystemCounters by one.

AdminNotes

You can see, from the example, that I know that the workflow ran step 1 at 2:03pm on 5/15/2008. I know the step completed, and what it did. The link in the Admin Notes opens the original item so that I can check it. The workflow log allows you to easily troubleshoot a failed workflow – and it has the advantage that it works for Custom Form Actions (which have no history at all?).

Organising the Log

The log continues to compile workflow entries in the background as my users continue to work in the application. I can sort the log by the date the event occurred or by the workflow name, etc. I also have another field, specific to my company, which contains the “ticket number”. I can sort the workflow log by the specific ticket number, then the workflow name, and then the date and time. I have an admin page that contains a multiple item dataview of the log and allows me to select the ticket number from a drop-down list to filter the available entries. 

Future efforts

I am going to add a new column and link to the workflow. I want a column that stores a link to the actual SharePoint workflow history. If you open the workflow history on an existing item, the URL in the address bar looks like this:

http://mysharepointsite/sites/main/_layouts/Workflow.aspx?ID=72&List=B65934BA-EBF4-4CB8-956D-B0Ce4236B657 

The ID number identifies which specific entry the workflow was run on and the List number identifies which list the entry resides in. I will create a hyperlink that takes the ID from the current item (Dataview) and substitutes the List number as a variable as well.

I think that this log process contains a lot of untapped potential and I will be updating this post as I add to the log.

UPDATE

Paul Galvin pointed out that I forgot to mention some  of the possible downfalls to this logging method. You can see his blog here

Thanks for Reading

May 16, 2008 at 1:31 pm 8 comments

Create a Virtual Time Card System

Disclaimer: I found this tip on the web in a forum or site – but I can’t remember/locate the original source. If anyone knows the original source, please let me know.

I haven’t attempted this yet, and I would probably add some more detail to the instructions – but I want to get the basic idea up on the blog so I don’t lose the piece of paper I scribbled it on.

The Basic Scenario

The user clicks a button to “punch in” when the start work. The button creates a new item in a list and the system records the UserName, Time, Date, Department and TimeIn.

At the end of the workday, the user clicks the “punch out” button. The button creates a new item in a different list and that launches a workflow that edits the original item and recrds the UserName, Time, Date, Department and TimeOut. The workflow then populates a rich text field with the contents of both items.

At the end of the week, compile the contents of all of the records for all of the days of the week into one rich text field for the manager.

My Updates

Can the punch in process not be automated? When the user opens the Intranet Home page – you can grab the user logon credentials from server variables and then create the item automatically?

Instead of a rich text field with all of the records dumped into it, a multiple item dataview which is filtered by a drop-down (select username) would be much more organised.

Add an approval process and allow the manager to email the approved timesheets to the HR department – or send unapproved timesheets back to the original users to correct any mistakes. 

 

May 14, 2008 at 2:28 pm Leave a comment

Design Tip 4: Turn Any Field in a Dataview into a Hyperlink

Any field in a Dataview (single or multiple item view) can be converted into a hyperlink to allow users to jump to the item in detail.

In one of the web applications I have created, the main page shows a customised multiple item Dataview that allows the user to see all of the currently open tickets and the status they are in. There are columns for Ticket Number, Edit Ticket, Comment, etc.

The Ticket Number is a hyperlink field that takes the user to a customised Dispform.aspx page where they can see a read only version of the ticket details. The Edit Ticket column contains hyperlinks to a customised Editform.aspx. The Comment column has hyperlinks which take the user to a customised Newform.aspx page to enter comments (in a different list).

The one thing that all of the lists in the application have in common is the Ticket number field. The hyperlink for the Comment column looks like this:

<a href=”http..sharepointsite/lists/newform.aspx&Ticket={@Title}” OnClick=”GoToLink(this);return false;”  target=”_self”>Comment</a>

Because the hyperlink is contained within a Dataview, you can access the variables from the dataview. The system will place the “Title” field value into the URL for the ticket I am clicking on. If I click the Comment hyperlink on ticket 12, it will place a 12 in the URL. The target form uses a Query String to access the Ticket variable and the new Comment is created for that ticket.

Click here to learn about defaulting values on a new item form:

https://splittingshares.wordpress.com/2008/04/22/defaulting-a-hidden-field-on-a-form/

May 14, 2008 at 2:15 pm Leave a comment

Design Tip 3: Custom Actions on Form Buttons are just like Workflows

Form buttons can have Form Actions associated with them. Form Actions can contain Custom Actions. Custom Actions in Form Actions are configured just like workflows – the main difference is that they don’t initiate until the button is pushed. 

I have been moving a lot of my workflows into Custom Form Actions. I like the fact that they only get started when the button is pushed. For example, when a user edits a specification in my web application and clicks Save, the Custom Form Action checks the current status of the specification. If the specification was in Created status, it saves the specification and changes the status to In Progress. If the specification was in Review status, it emails all of the Reviewers to let them know it has been changed and then sets the status back to In Progress.

Important: I have come across one major problem using this tip. The Custom Form Actions don’t seem to have a workflow history. There is no way, that I can find, that allows me to see when the Custom Form Action ran, where it got stuck and what the current status is. This can be a nightmare when trying to troubleshoot any issues.

Workaround: I have created a custom list to track workflow statuses. After a workflow completes any step – I have it write to the custom list – this way when a workflow or custom form action fails, I can check what the last correct step was. I think that I will post a more in-depth topic on logging workflows.

May 14, 2008 at 2:13 pm 6 comments

Design Tip 2: Deleting and Restoring a List Item destroys Workflows

I had several workflows in my web application that would start when a new item was created and then pause for a duration or wait for a field to change. The user would create an item, the workflow would start and then it would wait for the status field to equal Completed.

If you delete the list item, in my case it was by accident, and then restore the list item, the workflow remains in the waiting status forever.

Hopefully someone with some real in-depth SharePoint knowledge reads this and they can explain why it behaves this way?

May 14, 2008 at 2:12 pm Leave a comment

Design Tip 1: Hyperlinks Should Always Contain the Source

This tip was taken from SharePoint Online Help Topic – Return your Customer Back to your Data View

Original topic: http://office.microsoft.com/en-us/sharepointdesigner/HA102403641033.aspx

When a user clicks ANY link in a web application I have created, the URL passed to the new page contains the source location the user came from. If you examine the URL in the default lists and items in SharePoint, you will notice that they almost always contain the ‘&Source’ variable.

Why?

If the URL contains the source, you can use it in a Query String variable or in a Navigate to Source Form Action. You will be able to control how a user moves through your web application and therefore control the user’s actions and perceptions in the application. If you control there perception in the web application, there is nothing you cannot do.

When a user clicks the Create New Item link on a page on my site, they will be redirected to the Newform.aspx page I have customised (the page could be called anything because I control where the hyperlink points). But, when the user clicks Save or Cancel on the new form, where is the user sent?

I like to have the user automatically redirected to the next step, or sent back to the page they came from.

Add the code to the Hyperlink

Hyperlinks should contain the following attributes in the <a> tag to let the system know which page the user came from. A normal hyperlink might look like the following:

<a href=”http://..mysharepointsite/folders/link…”>link text</a>

In order to enable the source variable in SharePoint, all you need to add is the following attributes:

OnClick=”GoToLink(this);return false;”

target=”_self”

The new hyperlink would look like this:

 <a href=”http://..mysharepointsite/folders/link…” OnClick=”GoToLink(this);return false;”  target=”_self”>link text</a>

When the user clicks the the new link text, the target page will open and the URL in the address bar will contain the ‘&Source’ variable.

Put that Information to Good Use

The URL now contains a variable for the user’s source page, so what? How do I leverage this new found super power?

Form Buttons

If you right-click on a form button (for example, the Save or Cancel button), you will see an option for Form Actions in the pop-up menu. Select Form Actions and you will open the Form Actions dialog box. You can now add the Navigate to Source action to the button and when the user clicks it, the button will perform it’s action (for example, Commit or Cancel) and then return the user to the page they came from.

May 14, 2008 at 2:10 pm Leave a comment

Older Posts Newer Posts