3

I'm trying to build an app that has a list with a custom form. I've looked at client side rendering and all of the documentation I've seen is about specific field overrides. However, the form I want to make needs to submit different items to more than one list, and multiple items to one list (essentially a one-to-many relationship between the primary list and other lists in the app), but I haven't found documentation on using CSR to do such extensive form customisation. Could anyone point me in the right direction, or is trying to customize forms the way I want this way a dead end?

1 Answer 1

7

To create a form that would submit items to multiple lists, you should:

  1. Add some elements to your main list form, probably arranging them in a certain way. If those elements aren't related to fields as I suspect from your description, best way to do it would be to leverage OnPostRender CSR event and then use HTML5 selectors or jQuery to insert your HTML into the right position - before, between or after the form fields.
  2. Intercept form submit event, and add some JSOM code for inserting items into the external lists.

Please be aware that this can be a bit messy. For example, if server-side form validation fails, you might end up with external list items added, but the main list item not added.

Using CSR OnPreRender to insert something into the form

In the Standard rendering mode (which is the default one), CSR is in fact launched over and over again for every field of the form. Thus OnPreRender will be called multiple times, and the only element in ctx.ListSchema.Field array will be the current field.

So you can use ctx.ListSchema.Field[0].FieldName to determine the current field name, and insert HTML after or before certain fields.

Since OnPreRender is just an event and it cannot directly emit any HTML into the page as the CSR handlers can, you'll have to use jQuery or js for this, by selecting DOM elements and appending your HTML after them. Below I'm using pure JS to minify the dependencies of the solution.

So here comes the sample code, where I insert additional <tr>, marked with red borders, after the Title field:

SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
    OnPreRender: function(ctx) {
      var fieldName = ctx.ListSchema.Field[0].Name;
      if (fieldName == "Title")
      {
          var span = $get(ctx.FormUniqueId + ctx.FormContext.listAttributes.Id + fieldName);
          var tr = document.createElement('tr');
          tr.style.backgroundColor = "#ada";
          tr.innerHTML="<td colspan='2'>&nbsp;</td>";
          var fieldTr = span.parentNode.parentNode;
          fieldTr.parentNode.insertBefore(tr, fieldTr.nextSibling);

      }
    }
  });

Result of performing this customization:

enter image description here

How to apply CSR customization to the list form

For the sake of comprehensiveness, I'm also including explanation of how to apply the customization to the form.

The answer is simple: just put the JavaScript I provided above to the page using whatever method you like.

It can be as simple as just adding Script Editor Web Part to the page and pasting the code there. Or you can leverage JSLink for that (by editing list form web part properties):

enter image description here

Sometimes it is also convenient to deploy the js via Schema.xml. And so on...

Intercepting the form submit

Now, once you inserted your HTML and thus prepared the UI, you need to take care about actually putting the data into external lists.

Notice, that obviously you need to validate the additional data user tries to submit, and if something is wrong, then form submission must be canceled. So it's not just subscribing to the event, but indeed intercepting it.

To do this, you can redefine the SPClientForms.ClientFormManager.SubmitClientForm function, that manages submission of CSR-enabled forms.

Here is the original SharePoint version of this function:

SPClientForms.ClientFormManager.SubmitClientForm=function(b){
    var a=SPClientForms.ClientFormManager.GetClientForm(b);
    return a!=null&&a.SubmitClientForm()
};

Now, you can redefine it and include some additional JSOM code to the beginning of the function. This code would validate the custom UI and create list items in external lists.

If your custom validation failed or for whatever reason you want to prevent the submission, just return true before execution reaches the SubmitClientForm call.

Finally, here is an example of code for adding a list item with JSOM (from MSDN):

var siteUrl = '/sites/MySiteCollection';

function createListItem() {

    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');

    var itemCreateInfo = new SP.ListItemCreationInformation();
    this.oListItem = oList.addItem(itemCreateInfo);

    oListItem.set_item('Title', 'My New Item!');
    oListItem.set_item('Body', 'Hello World!');

    oListItem.update();

    clientContext.load(oListItem);

    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onQuerySucceeded() {

    alert('Item created: ' + oListItem.get_id());
}

function onQueryFailed(sender, args) {

    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
1
  • Andrey, after a.SubmitClientForm() call is there a way to prevent form from closing?
    – dbardakov
    Commented Dec 8, 2015 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.