- Part 1 - Overview, URL Tokens and Applying JSLink to objects
- Part 2 - Changing how individual fields display
- Part 3 - Creating a custom editing interface (this post)
- Part 4 - Validating user input
- Part 5 - Creating custom List Views
- Part 6 - Creating View Templates and Deployment Options
- Part 7 - Code Samples
Now the process for creating an editing interface is identical for both "New" and "Edit" forms (with the exception that the editing interface also needs to deal with loading up existing values) so for this post our examples will focus on the "Edit Form" functionality.
Registering our Edit Form function
So this uses exactly the same technique that we walked through in Part 2, where we register our desired override method for our named field.
(function() {
var mjhOverrides = {};
mjhOverrides.Templates = {};
mjhOverrides.Templates.Fields = {
'MyCustomField': {'NewForm': mjh.editMethod,
'EditForm': mjh.editMethod
}
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(mjhOverrides );
})();
So just like before we create ourselves an override object and tell it we want to use the method "mjh.editMethod(ctx)" to render both the "EditForm" and "NewForm" for our field "MyCustomField" and we then register that using the SPClientTemplates.TemplateManager.RegisterTemplateOverrides method.
The Edit Render Method
The format of the rendering method for the edit interface (in this example) is pretty straightforward. I have simply rendered out a drop-down list containing three items.
mjh.editMethod = function (ctx) {
var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);
formCtx.registerGetValueCallback(formCtx.fieldName, mjh.getFieldValue.bind(null, formCtx.fieldName));
// items to appear in the drop down list
var items = new Array("Item 1", "Item 2", "Item 3");
var returnHtml = "<div id=" + ctx.CurrentFieldSchema.Name + "><select>";
for (var i = 0; i < length; i++) {
returnHtml += "<option";
if (ctx.CurrentFieldValue == items[i]) {
// select the current item if the value matches
returnHtml += " selected ";
}
returnHtml += ">" + items[i] + "</option>";
}
returnHtml += "</select></div>";
return returnHtml;
};
We have also made use of the JavaScript "bind" function so that we can specify arguments that should be passed to our callback method, in this case we want to pass the field name (you'll see why in a minute).
The only other thing special going on here is that I check to see if the current value of the item matches the option, and if it is we add the "selected" attributed.
We have also enclosed the whole thing in a div using the fieldname as the ID, which we can use in our callback method below ...
The Get Value callback
The next thing of course is our method to retrieve the actual field value, and for this we use a little bit of jQuery (you can choose your own way of getting the jQuery library onto the page. Adding it as an extra JSLink URL is quite cool, although if you use jQuery everywhere you might otherwise want to use a Custom Action or Delegate Control so it appears on every page).
The only other thing special going on here is that I check to see if the current value of the item matches the option, and if it is we add the "selected" attributed.
We have also enclosed the whole thing in a div using the fieldname as the ID, which we can use in our callback method below ...
The Get Value callback
The next thing of course is our method to retrieve the actual field value, and for this we use a little bit of jQuery (you can choose your own way of getting the jQuery library onto the page. Adding it as an extra JSLink URL is quite cool, although if you use jQuery everywhere you might otherwise want to use a Custom Action or Delegate Control so it appears on every page).
mjh.getFieldValue = function (fieldName) {
// a div used with jQuery to identify the appropriate items
var divId = "#" + fieldName;
var divId = "#" + fieldName;
// get the selected item
var selectedItem = $(divId + ' option:selected')[0];
var selectedItem = $(divId + ' option:selected')[0];
// return the value
return selectedItem.innerText;
return selectedItem.innerText;
};
So you can see above that we are using the fieldName argument so we can identify the correct div. This allows us to use the same methods on multiple fields without them clashing.
We then simply use a small jQuery statement to pull out the selected item (the "option" element which has an attributed of "selected") and return the "innerText" (which in our example is the value we want to save). Of course you need to be mindful of the data type of the field you are working with. All values are returned as Text but fields such as People and Lookup Fields need to return a specifically formatted string.
I then bound this to a site column (of type Text) with the following schema:
<Field ID="{A424AE9E-1F1D-4ECE-B695-202F5106352E}"
Name="MyCustomField"
DisplayName="My Custom Field"
Description="a text field which has custom rendering?"
Type="Text"
Required="FALSE"
Group="MJH JSLink Columns"
JSLink="~layouts/MJH.JSLink/jquery-1.10.2.min.js|~layouts/MJH.JSLink/MJH.JSLink.js"
Overwrite="TRUE">
</Field>
Once that is all deployed it should look something like this ...
My Custom Field - a Text field but rendered as a drop-down list
|
In the meantime you can download the sample code from this example here:
http://sdrv.ms/14KtFgv
...
Next - Part 4 - Validating user input
Hi Martin
ReplyDeleteGreat Article !
Can we do this OOTB ie without the use of Visual Studio.
I have an Office 365 site but the customer has banned anything emanating from Visual Studio.
PS Why cannot I use my LiveID to comment ?
Yes you can, if you read Part 1 you'd know you can just upload your JS files and reference it from the Web Part Properties :)
ReplyDeleteRegarding LiveID .. this is running on Blogger (aka Google) and they don't support LiveIDs