Creating Open & Close Dates for a Browser-based InfoPath Form in SharePoint 2010

The Situation

We often use forms to collect data. Sometimes, we need to limit the time during which people can submit data to a certain set of open and close dates. It’s certainly possible to go change permissions on the underlying list or library to take away contribute permissions when outside the open time period. But, that relies on a person remembering to do it on time, and it’s confusing for people to have the UI change (no more “add new item” option) with no explanation of what’s going on. Also, when building forms for less tech-savvy site owners, changing permissions can be confusing.

The Solution

Using a combination of SharePoint lists and InfoPath forms, it’s possible to create a solution that is easy for site owners to manage and gives clear and concise information to end-users.

The Set Up

You’ll need 2 lists.

The Open/Close List.

Create a custom list. I called mine “Open and Close Dates.” This list should have 3 columns – the title, the open date (date & time column) and the close date (date & time column). The title will be used to filter the open/close dates when we pull them into the InfoPath form, so that you can open and close more than 1 form with the same list.

The list for setting the open and close dates.

The list for setting the open and close dates.

The form list

In my case, I’m using a custom list with a custom content type. But, it should work for any custom list.  There are a couple of important settings here. First, on list settings -> advanced settings, make sure that Datasheets are disabled. Otherwise, users will be able to circumvent your InfoPath form.

Make sure bulk edit is not allowed.

Make sure bulk edit is not allowed.

Second, since none of this magic happens without InfoPath, we want to click the “Customize Form” button to customize the form used with the list in InfoPath Designer.

Click the "Customize Form" button to open InfoPath Designer

Click the “Customize Form” button to open InfoPath Designer

The InfoPath Magic

Once in InfoPath, there are a few steps to get this all working.

  1. Set up a data connection to your “Open and Close Dates” list. (For step-by-step directions with pictures for creating a connection to a SharePoint List, check out Wonder Laura’s post.)
    • Click the “Data” tab and click “From SharePoint List”.
    • Enter the site URL.
    • Select your open/close list.
    • Check off the following: Title, Open Time, Close Time (sorting is irrelevant in this case)
    • Name your data connection whatever you’d like.
  2. Create Open and Closed fields and set their default values
    While we can pull the open and closed fields from the data connection we created in step one, there are places where we can’t filter on the fly if we have more than one value in the open/close list. So, we need to create open and closed fields in our main data connection, or in a dummy one. I did it in the main data connection, because I don’t really care if we have a couple extra columns of data in our form list. But, if you’d prefer to set up a dummy data connection, John Liu has a great post on doing that. Here’s what I did.

    • In the main data connection, click “Add Field”.

      Add a Field to the Main Data Connection

      Add a Field to the Main Data Connection

    • Set the display name to “open.”
    • Click the “fx” button for the default value.
    • Select “Insert Field or Group.”
    • Click “Show Advanced View.”
    • Choose the Open and Close Dates datasource.
    • Open the “dataFields” folder.”
    • Select “Open Time.”
    • Click “Filter Data.”
    • Click “Add.”
    • Select “Title” in the first drop down and set it equal to whatever text you set in as the title in the list.
    • Click “Ok” on all the open dialog boxes.
    • Your field properties should look something like this:

      Example of the "open" field.

      Example of the “open” field.

    • Repeat process to create a “closed” field.
  3. Create a “Closed” view.
    • Click the “Page Design” tab.
    • Click “New View.
    • Enter a name. (I called mine “Registration Closed.”)
    • Type whatever “form closed” message you want. Mine pulled in the open close dates and displayed them, like so:

      Sample "Closed" View

      Sample “Closed” View

  4. Set Form Load Rules
    Steps to set a form load rule to switch views to "closed form" view.

    Steps to set a form load rule to switch views to “closed form” view.

    • Click the “Data” tab.
    • In the “Rules” section, click “Form Load.”
    • Click “New” and select “Action.”
    • In the “Conditions” section, click “None” to set conditions.
    • You need 3 conditions: open > now() OR close < now AND title is blank. (Open and Close are the fields in the main data connection that you set up in Step 2. Ensuring that title is blank means this will only run when a new form is loaded.)

      Form Load Conditions

      Form Load Conditions

    • In the “Run these actions” section, click “Add” and select “Switch Views.”
    • Select your “Registration Closed” view.
  5. Add a Submit Button to the “Edit Item (default)” View
    In our next step we’re going to remove the InfoPath buttons. So, our users need a way to submit their data, but only when the form is “open.”

    Add a Submit Button inside a section. Hide the section when form is closed.

    Add a Submit Button inside a section. Hide the section when form is closed.

    • At the bottom of the form, add a new section. (Home Tab -> Controls -> Containers -> Section)
    • In this section, add a button.
    • Right click on the button and select “Button Properties.”
    • Set the Action to “Submit.” You can modify the label if desired, or leave it as the default.

      Submit Button Properties

      Submit Button Properties

  6. Hide the Submit Button Section when form is closed.
      • Click on the section tab, and click “Manage Rules.”
      • Click “New” and select “Formatting.”
      • Click “None” under “Condition” to open a menu for setting conditions.
      • Here we need 2 (or possibly 3) conditions. The 2 that are a must are: open > now() AND close < now(). If you have an administrator that should always be able to edit data, you’ll want to add a third condition. This one is “OR xdUser:get-Username() != “youradminusername.”
    Set the rules to hide the submit button section when closed and not being viewed by an admin.

    Set the rules to hide the submit button section when closed and not being viewed by an admin.

    Check the “Hide this control” checkbox.

  7. Create a “Registration Closed” notice on the form.
    Create a section at the top of the form to indicate closed status.

    Create a section at the top of the form to indicate closed status.

    • At the top of your form, create another section. (Home Tab -> Controls -> Containers -> Section)
    • Add a message to indicate registration is closed. Mine says, “Registration is currently closed. You can not submit or edit registrations at this time.”
    • Click on the section tab, and click “Manage Rules.”
    • Click “New” and select “Formatting.”
    • Click “None” under “Condition” to open a menu for setting conditions.
    • On this section, you need the opposite conditions as the submit button, because you want this one hidden when the form is open. So, you need: open < now() AND close > now(). If you don’t want the administrator to see it, then you need the expression “xdUser:get-UserName() != ‘YourAdminUser’.”

      Conditions for the form closed notification.

      Conditions for the form closed notification.

  8. Remove the Infopath buttons.
    • Click the “File” tab.
    • Click “Form Options.”
    • Click “Web Browser.”
    • Uncheck “Show InfoPath commands in Ribbon or toolbar.

      Uncheck InfoPath Commands in the Form Options

      Uncheck InfoPath Commands in the Form Options

The Finished Product

With everything set up, when users come to the site, they will always be able to click the “Add New Item” button on the list, but if data collection is closed, they’ll receive a friendly message with an explanation.

Closed notice displayed when add new item is clicked.

Closed notice displayed when add new item is clicked.

When a user attempts to edit an existing registration, they’ll be notified that the registration is closed, and there will be no submit button for saving changes.

Editing a closed form shows the notice and removes the submit button.

Editing a closed form shows the notice and removes the submit button.

The Caveats

Hey, it’s SharePoint. You know there are some.

What I’d really like to be able to do is to determine the state of the form when it opens. Is it in edit or view mode? If in edit mode & registration is closed, switch to the closed view. If it’s in view mode, don’t. Alas, I’ve yet to be able to figure that one. Got any ideas?

SP2010: Using PreSaveAction on Custom Forms

The Situation

You have a list that has list-level validation. But, you need to use a customized new item or edit item form. The validation routine fires on the server, but the custom new and edit forms do not show the associated error. While you could handle your validation with a workflow or a custom event receiver, there’s a simpler way.

The Work-Around

In addition to the existing list-level validation, you can add client-side validation by hooking into the PreSaveAction function. In my particular case, I had three columns that needed to equal each other. There are several moving parts involved.

  1. In the custom new item and edit item forms, create a div to show or hide errors. Default it to not being shown when the page loads. Include your standard error text. (NOTE: You can modify the error text via your JavaScript function later on, if you have multiple validations to run.)
    <div class="ms-formvalidation FormErrors" style="display: none;">The total contacts by race, ethnicity, and gender must match.</div>
  2. In the custom new item and edit item forms, add a call to the PreSaveAction function in the code on the page. (NOTE: You can’t include this as an external file. It must be on the page itself.)
    <script>
    // Stupidly, this function can't be included in an external file, so we'll call the function here and just return another function from the external file.
    function PreSaveAction() {
    return PreSaveExternalAction();
    }
    </script>
  3. In a text file in SiteAssets, create your corresponding validation function. (Note: your function can not be inside a $(document).ready(function(). It won’t be called if it is. The name of the function in your external file should match the name of the function returned by the PreSaveAction function.)
    function PreSaveExternalAction() {
    if (($('#TotalContactsByRace').val() != $('#TotalContactsByEthnicity').val()) || ($('#TotalContactsByRace').val() != $('#TotalContactsByGender').val())) {
    $('.FormErrors').show();
    return false;
    }
    else{
    //if all is good, return true
    $('.FormErrors').hide();
    return true;
    }
    }
  4. Include a Content Editor Webpart on your custom new and edit item pages which links to your external text file.

    Create a link to the Javascript File

    Create a link to the Javascript File

When you test your page, you should see your validation working. In my TotalContacts.txt file, I do on-the-fly validation as well as the PreSaveAction validation. It’s always a good practice to let people know that there is an error before they try to submit.

Showing the validation error

Showing the validation error

While you could include all your validation in the PreSaveAction function itself, you’d need to repeat your validation code on both the new and edit forms. Anytime I find myself repeating code, I try to find a way to make that piece of code reusable. By having the PreSaveAction function just return another function, we can write that code once, and use it on both the new and edit forms.

Download a copy of the entire TotalContacts.txt file.

Calendar Overlay – a simple SharePoint 2010 OOTB Master Calendar

A master calender is a common request for team sites that have sub-sites. If you are running SharePoint 2010, there’s now a built-in way to do a roll-up master calendar using the calendar overlay feature.

The Steps

  1. At the site on which you want to display the master calendar, either create a calendar list or use the existing team site calendar.
  2. On the Calendar tab in the ribbon, click Calendars Overlay.

    Calendar Overlay Button on the Ribbon

    Calendar Overlay Button on the Ribbon

  3. Click the New Calendar link to add a new calendar.

    Click the New Calendar Link

    Click the New Calendar Link

  4. In the next screen, you will need to provide information about the calendar you are adding (name, description, etc.) plus the URL of the site that houses the calendar. *(Note that the URL should be to the site, not to the calendar itself. SharePoint will find all the possible lists and views once you click the Resolve button after entering the URL address.) If the site has multiple calendar lists or views, you will need to select the one you wish to overlay from the drop down boxes. Check the box next to Always Show. Click OK.

    Enter Calendar Information

    Enter Calendar Information

  5. Repeat Steps 3-4 for each calendar you wish to add.
  6. When all the calendars are added, click “Ok.”
  7. Now all the calendars will show on the main calendar.

    Combined Calendar View

    Combined Calendar View

The Caveats

You knew there were some, right?

  1. You can only include 10 calendars.
  2. You only have 8 colors to choose from.
  3. You can include calendars that are above the site of the “master calendar” and that are siblings to the master calendar, and even that aren’t in the same site collection (Yay!). But, if the person visiting the site doesn’t have permissions to view the other calendar, you’ll get this error:
    Permissions Error

    Permissions Error

    Oops. So, be careful with permissions on your overlays.

  4. If you connect to Outlook on the main calendar, it will not include the overlaid calendars.
  5. If you add a web part of the master calendar to a page, it will not include the overlaid items you have to switch to “calendar” view in the web part properties to see the overlaid items.
  6. You can overlay lists that are not of the calendar type, as long as they have a calendar view. (This isn’t really a caveat – just a good thing to note.)
You can also overlay Exchange calendars. Sharad Kumar has a good blog post on how to aggregate Exchange Appointments into a Calendar View.