Saturday, March 30, 2013

How to create dynamic forms with Forms Designer in SharePoint 2010

In the first post I would like to show a simple case of customization SharePoint 2010 forms with Forms Designer tool. I will create form with tabs and tables and add basic dynamic with JavaScript.

Last week I worked on Help Desk system. I started with template 'Help Desk' from CodePlex project and implement some modifications. Next I needed to design forms for requests to make it simpler and more usable. The default form has the following view:

SharePoint standard form


There are many fields, some of which user doesn't have to define himself, for ex.: Resolution Type, Resolution Date etc, cause they have to be filled by the person assigned to the request. And some should be predefined automatically in most cases, for ex.: if author and customer are the same person Customer field has to be filled with current user value. Also, it would be great to organize fields in categories: Main (required info), Resolution and Links.

So, I decided to distribute fields into tabs with Forms Designer tool, add autofilling to Customer field with current user and hide resolution fields if status of the request is not 'Resolved' or 'Closed'. For the last two tasks I used Forms Designer JavaScript framework that allows to manipulate fields in JQuery manner.

After 5 minutes of manipulation with Forms Designer's drag-n-drop interface I got the following form:

SharePoint form with tabs and complex tables

SharePoint form with tabs and complex tables

Looks nice. Now we can further simplify this form:
  1. Resolution tab is useful only if status of the request is 'Resolved' or 'Closed'. So, I will hide it for other cases.
  2. In most cases customer and author are the same person. So, I will prefill this field with current user info.

Resolution tab

In the Forms Designer I opened JS-editor window and put the following code to disable 'Resolution' tab when Status field equals 'Close' or 'Resolved':
// Enable or disable 'Resolution' tab 
function setResolutionTab() { 
    var v = fd.field('Status').control().value(); 
    if (v == 'Closed' || v == 'Resolved') { 
        $('#fd_tabcontrol-0').tabs('option', 'disabled', null); // Enable 
    } else { 
        $('#fd_tabcontrol-0').tabs('option', 'disabled', [1]); // Disable 
    } 
} 

// Subscribe on status change 
fd.field('Status').control().change(function () { 
    setResolutionTab(); 
}); 

// Initialize 
setResolutionTab(); 
To hide disabled tabs I added following CSS directly to the Forms Designer:
.ui-tabs .ui-state-disabled {  
    display: none; /* disabled tabs don't show up */  
}
Great. Now when user sets status to 'Initiated' or 'In progress' they see only two tabs:

SharePoint dynamic form

Autofilling

I added this function only on a new form. The following code loads the current user login and pass it into the Customer field:
// Load current user login 
SP.SOD.executeOrDelayUntilScriptLoaded((function () { 
    var ctx = new SP.ClientContext.get_current(); 
    var web = ctx.get_web(); 
    ctx.load(web); 
    var user = web.get_currentUser(); 
    user.retrieve(); 
    ctx.executeQueryAsync( 
    function () { 
      // Set user login 
      fd.field('Customer').control().value(user.get_loginName()); 
      // Run validation by emulating validation image click
      fd.field('Customer').control()._el().find('a:eq(0)').click(); 
    }); 
}), "SP.js"); 

Method _el() of the FDControl class returns control's div-wrapper as JQuery-object. So, if you work with custom fields and the Forms Designer doesn't know where the field stores its value, you may use this method. And here it was also helpful to click on the validation link in the people picker field.

I can answer your questions in the comments. Thank you.

33 comments:

  1. Hi, do you support Managed Metadata fields?

    ReplyDelete
  2. Hello Half,
    Sure, you can use any standard and custom fields with Forms Designer.

    ReplyDelete
  3. Great. Do you think it's possible to implement a "conditionally required field"? (field B is required if field A equals "X")

    ReplyDelete
    Replies
    1. Sure, you have to remove standard SharePoint validation (field B have not to be required) and add your own logic with Forms Designer's JS-framework: http://spform.com/documentation/js/control. Our support can help you with this task, write them to support@spform.com

      Delete
  4. Hi Tim,

    This is awesome! We are currently testing the trial now and we would just like to ask how can we re-size a drop-down list? Just like Status, Priority and Keywords in this example, how can we make them aligned? We already tried to re-size it by adjusting the width but it doesn't seem to be working. Please help.

    Thank You,

    Arnel

    ReplyDelete
    Replies
    1. Hello Arnel,

      I did not make any special modifications for this. It's their default view. Did you add custom CSS to your master-page or form? You can export your form with Forms Designer, save your list as template and send both form and list template to support@spform.com. I'm sure, our support team will help you with this issue.

      Delete
    2. If you wish to fix width your drop-downs you can use CSS. Define CSS-class in the properties of your drop-down fields, for example 'dd'. Then open CSS-editor and define the following style for your class:

      .dd select {
      width: 400px;
      }

      Now the width of your drop-down will be fixed on 400 pixels.

      Delete
    3. Wow! Thank you very much Tim. Adding this CSS code works. :) Also, thanks for letting us know that we can send our list and forms to you guys for further assistance. Cool!

      Thanks again,

      Arnel

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Hi Tim,

    I was wondering if its possible to hide the tabs using permisions?

    Thanks,

    Katerina

    ReplyDelete
  7. Is there a list of CSS fields that are defined for reference? I'm trying to vertically center a hyperlink in a table cell but I don't know what the name of the field is in order to reference it in CSS.

    ReplyDelete
  8. I love this example, very helpful. There is a functionality bug that should probably be fixed in the article above, if possible, and I have a comment.

    First, I am having a hard time finding documentation on the .tabs() method used above. With some trial/error I figured out how it worked. Since I was trying to hide the 4th tab on my form, I had to change the last parameter to [3]. Links to documentation on that? Would be appreciated.

    Usability bug: If the user is currently on the tab that is being shown/hidden (with the CSS above), and they hide the tab, their view of the tab's contents remains. I put in a line to move them back to the first tab every time they disable the control, but it would be better to first detect the active tab, and only change the active tab if the current one is the tab being hidden.

    Thanks,
    Seth

    ReplyDelete
  9. I'm trying to perform the same action using the accordian feature of SharePoint Form Designer.

    I currently have the accordian section placed in a table with a CSS Class. How can I reference this CSS Class in the javascript to hide it when a dropdown menu entry is selected?


    Thanks,

    ReplyDelete
    Replies
    1. Hi,
      Do you mean you need to hide a particular accordion section or the whole accordion with all its sections?

      Delete
    2. Hi Dmitry,

      It's the whole accordion with all content so sections, text labels etc.


      Thanks

      Delete
  10. How do i hide a tab when a check-box is unchecked?

    ReplyDelete
    Replies
    1. Almost the same way as described in this post. Just use he following code to get the check-box status:

      if (fd.field('CheckboxField').value()) {
      // Checked
      } else {
      // Unchecked
      }

      Delete
  11. I am able to disable the tab but is there a way completely empty all the fields inside the tab and hide it?

    This tab has following columns
    AFH_x0020_Projected_x0020_CY_x00
    AFH_x0020_Company_x0020_Auto

    code i am using:

    // Enable or disable 'Incentive' tab
    function setIncentiveTab() {
    if (fd.field('AFH_x0020_Sales_x0020_Position').value()) {
    $('#fd_tabcontrol-0').tabs('option', 'disabled', null); // Enable
    } else {
    $('#fd_tabcontrol-0').tabs('option', 'disabled', [1]); // Disable
    }
    }

    // Subscribe on status change
    fd.field('AFH_x0020_Sales_x0020_Position').control().change(function () {
    setIncentiveTab();
    });

    // Initialize
    setIncentiveTab();

    ReplyDelete
  12. I have the following JS code which works if I do not make the field read-only, however I need AllUsers to have the LifecycleStage field read only.

    I tried to use a calculated field instead but this did not work either. The calculated filed is PMOLifecycleStage.

    Any ideas on how I can make it work?

    // Initiate TAB
    function setInitiateTab() {
    var v = fd.field('LifecycleStage').control().value();
    if (v == '(2) Initiate') {
    $('#fd_tabcontrol-1').tabs('option', 'disabled', [2,3,4,5]);
    } else {
    $('#fd_tabcontrol-1').tabs('option', 'disabled', null);
    }
    }

    // Subscribe on status change
    fd.field('LifecycleStage').control().change(function () {
    setInitiateTab();
    });

    // Initialize
    setInitiateTab();

    ReplyDelete
    Replies
    1. Hi,
      Please, use the following code to get text representation of read-only field's value:
      fd.field('FieldName').control()._el().text()

      Delete
  13. Hi Dmitry,

    We have a requirement to make another field read only or not based on a People field equals the current user logged in.

    I know the code to make a field read only but don't know how to compare the current user logged in to a people field on the form. Can you please assist? Many thanks in advance.

    ReplyDelete
    Replies
    1. Hi,
      I'd recommend to use groups functionality in this case and create a separate form for the condition: ContainsCurrentUser([FieldName])
      http://spform.com/documentation/groups

      Delete
    2. Hi Dmitry,

      Thanks for the response. Understood. I have tried this but the user is not seeing the form. The user defined rule I am using is:

      ContainsCurrentUser([Assigned To]) || ContainsCurrentUser([Delegated To]);

      The people picker fields are using the new client render option. What am I doing wrong?

      Delete
  14. Hi Dmitry,

    Is it possible for the form to auto populate data into certain fields when selecting an option from a lookup? Such as selecting a name will pull the DoB and populate the DoB field on the form?

    Regards,

    Andrew

    ReplyDelete
    Replies
    1. Thanks Dmitry.

      I am trying to wrap my head around it at the moment. We are creating a form which will pull data from another list on our site. When we select the name from the lookup we want it to populate other fields with the other data already in that seperate list. I am assuming I would need to use an On-Change function in JS where On-Change of name it would then pull xyz data from the other list.

      Andrew

      Delete
    2. Hi Andrew,

      If you want to *copy* some related fields from a referenced list (if you don't need to update those fields in the referenced list via the form) you have two options:
      -use the standard SharePoint lookup field with additional fields (when you create the dropdown field select appropriate columns under 'Add a column to show each of these additional fields:'). The fields you'll get will be read-only and non-dynamic (when you change the lookup field, to see its related fields’ values you'll have to save and refresh). You can use these fields to prefill your current list's fields which you'll be able to edit (changes to them won't affect the original referenced list's field values). In order to do that you can add such an additional field to your form, make it hidden and use fd.field('InternalName').value() to get its value and then set to your editable field. You can do that in the JS editor, without any event handlers
      -use Cross-Site Lookup if you want to dynamically pre-fill those fields. In order to do this, when you create/edit your CSL field add the required additional fields to the query under 'Request Items' tab. For example, here we're adding a 'Flag' field
      function (term, page) {
      if (!term || term.length == 0) {
      return "{WebUrl}/_api/web/lists('{ListId}')/items?$select=Id,{LookupField},Flag&$orderby=Created desc&$top=10";
      }
      return "{WebUrl}/_api/web/lists('{ListId}')/items?$select=Id,{LookupField},Flag&$orderby={LookupField}&$filter=startswith({LookupField}, '" + term + "')&$top=10";
      }

      Then you can use the onchange handler (in the JS Editor) to get the field's value:
      fd.field('CrossSiteLookup').change(function(){
      fd.field('somefield').value(fd.field('CrossSiteLookup').control('data')['Flag']);
      });
      But you'll also have to set the value the first time the form loads:
      fd.field('somefield').value(fd.field('CrossSiteLookup').control('data')['Flag']);

      Delete
  15. Imagesretouch.com is a professional Clipping Path Service Company. We at Best Outsource Photo Editing Services, all our editors are professionally trained and they come with experience & expertise in their field and provides Real Estate Photo Editing Service and Image Retouching Services
    Images Retouch is an Image Editing Company and provides Image Editing Services and Photo Editing Services India
    Image processing Services
    Outsourcing Photo Editing Services
    Digital Marketing Agency in Hyderabad

    ReplyDelete
  16. How can I pass over a variable value using the URL and prefill it to an existing form.

    Example: /site/newForm.aspx?Name=Manuel

    ReplyDelete
  17. What is the syntax for hiding/disabling an accordion tab?

    I tried adapting the above code for a tab to an accordion, but it doesn't appear to be working.

    $('#fd_accordion-0').tabs('option', 'disabled', [4]); // Disable

    ReplyDelete
  18. Is there a way to display the current tab on load based on what month it is? For example I have tabs labelled January to December, like a calendar, and I want the current month tab to be active. I have created a calculated column that displays the current month as a number, e.g 11 for November. Thanks!

    ReplyDelete