Monday, January 2, 2012

Cascaded lookup – jquery and client object model

I’ve extended version from blog.libinuko.com. It’s more general and it supports both versions of lookup field (dropdown / autocomplete).
Thanks to the following scripts:
http://www.sharepointboris.net/js/spcd
http://blog.libinuko.com/2011/01/29/sharepoint-2010-how-to-create-cascading-lookup-field-using-client-object-model
Reference jquery.js and SP.js from your page.

<SharePoint:ScriptLink Name="SP.js" runat="server" OnDemand="true" Localizable="false" />

Javascript code for cascaded lookup:
// Cascaded lookup

function CascadedLookup(sourceFieldTitle, targetFieldTitle, targetListName, targetFieldInternalName) {
// Set variables
this.sourceFieldTitle = sourceFieldTitle;
this.targetFieldTitle = targetFieldTitle;
this.targetListName = targetListName;
this.targetFieldInternalName = targetFieldInternalName;
this.lastValue = null;

// Find source lookup field
var lookup = $("select[title='" + sourceFieldTitle + "']"); // 0-19 items
if (lookup.length == 0) {
lookup = $("input[title='" + sourceFieldTitle + "']"); // > 20 items
}

// Attach event handler to source lookup field
if (lookup.length != 0) {
var self = this;
if (lookup[0].optHid) {
// Input field saves value to hidden field
$("input[id='" + lookup[0].optHid + "']").bind("propertychange", function () { self.updateLookup(); });
this.autocomplete = true;
} else {
// Standard dropdown (select / option)
lookup.change(function () { self.updateLookup() });
this.autocomplete = false;
}

// Filter for current values
this.updateLookup();
}
}

CascadedLookup.prototype.updateLookup = function () {
// Get current value of source lookup field
var selectedValue;
if (this.autocomplete) {
var lookup = $("input[title='" + this.sourceFieldTitle + "']");
if (lookup.length == 0)
return;
var lookupHidden = $("input[id='" + lookup[0].optHid + "']");
if (lookupHidden.length == 0)
return;
selectedValue = lookupHidden.val();
}
else {
var lookup = $("select[title='" + this.sourceFieldTitle + "'] option:selected");
if (lookup.length == 0)
return;
selectedValue = lookup.val();
}

// Don't refresh when value didn't change
if (this.lastValue != null && this.lastValue == selectedValue)
return;
this.lastValue = selectedValue;

// Load filtered items for target lookup field
var clientCtx = new SP.ClientContext.get_current();
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("<View><Query><Where><Eq>" +
"<FieldRef Name='" + this.targetFieldInternalName + "' LookupId='TRUE' />'" +
"<Value Type='Lookup'>" + selectedValue + "</Value>" +
"</Eq></Where></Query></View>");

var list = clientCtx.get_web().get_lists().getByTitle(this.targetListName);
this.listItems = list.getItems(camlQuery);
clientCtx.load(this.listItems, "Include(Id, Title)");
clientCtx.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

CascadedLookup.prototype.onQuerySucceeded = function (sender, args) {
// Find target lookup field
var lookup = $("select[title='" + this.targetFieldTitle + "']"); // 0-19 items
if (lookup.length == 0) {
var lookup = $("input[title='" + this.targetFieldTitle + "']"); // > 20 items
if (lookup.length == 0)
return;
var lookupHidden = $("input[id='" + lookup[0].optHid + "']");
if (lookupHidden.length == 0)
return;

// Bind filtered items to target lookup field (input / autocomplete)
var choices = "";
var currentValue = lookupHidden.val();
var currentValueFound = false;
var listItemEnumerator = this.listItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var listItem = listItemEnumerator.get_current();
if (choices.length > 0)
choices += "|";
var id = listItem.get_id();
if (currentValue == id)
currentValueFound = true;
choices += listItem.get_item("Title") + "|" + id;
}
lookup.attr("choices", choices);
if (!currentValueFound) {
lookup.val("");
lookupHidden.val("");
}
}
else {
// Bind filtered items to target lookup field (select / option)
var options = "";
var currentValue = lookup.val();
var listItemEnumerator = this.listItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var listItem = listItemEnumerator.get_current();
options += '<option value="' + listItem.get_id() + '">' + listItem.get_item('Title') + '</option>';
}
lookup.html(options);
lookup.val(currentValue);
}
}

CascadedLookup.prototype.onQueryFailed = function (sender, args) {
alert("Request failed. " + args.get_message() + "\n" + args.get_stackTrace());
}

Sample:

var cascadedCountryCity;

function setupLookups() {
cascadedCountryCity = new CascadedLookup("Country", "City", "Cities", "CountryLookup");
}

// Attach function on document ready
$(document).ready(
function () {
ExecuteOrDelayUntilScriptLoaded(setupLookups, "SP.js");
});

No comments:

Post a Comment