If you look at this old post, you can see a technique that I used to hide a form field, and then append read-only data after it. I wanted to use this technique to hide a field in a form, append a replica with a jQuery autocomplete, and based on the selected value from the drop down, put the value in the original filed. I actually wanted a comma separated concatenation of all the selected values (multiple lookups). For example, I wanted to create a form to capture all the people at a meeting, the the attendees field would be hidden and replaced with a input box that can lookup contact GUIDs from a CRM, and once the contact is selected, the GUID is appended to the contents of the original Attendees field.
First up, the code to hide the field I want:
attendeesRow='<tr id="attendeesRow"> \
<td nowrap="true" valign="top" width="190px" class="ms-formlabel"><h3 class="ms-standardheader"><nobr>Attendee<nobr></h3></td> \
<td valign="top" class="ms-formbody" width="400px"> \
<div id="AddAttendees"><input type="text" id="AddAttendeesSearchTextbox" /> (add an EXISTING CRM Contact)</div><br/> \
</td></tr>';
$('nobr:contains("Attendees")').closest('tr').hide();
$('nobr:contains("Attendees")').closest('tr').before(attendeesRow);
Lines 1-5 is the code for the new replica field
Line 6 hides the existing field
Line 7 prepends the new replicate created in Lines 1-5
Next is the jQuery code to attach an autocomplete to the new text box (AddAttendeesSearchTextbox). I am using a little knockout to organize my code and I use some of the observable arrays to make the page more dynamic.
$('#AddAttendeesSearchTextbox).autocomplete({
source: function (request, response) { VM.contactsSearchSourceREST(request, response) },
delay: 600,
minLength: 3,
select: function(event, ui) {
var selectedObj = ui.item;
VM.addAttendee(selectedObj.fullname,"","",selectedObj.ParentCustomerIdName,"5",selectedObj.id)
$(this).val("");
return false;
}
});
And here is the javascript code (part of the view model) that is used for the source of the jQuery AutoComplete (CRM 2011 oData REST endpoint). Just a simple ajax call to CRM 2011.
self.contactsSearchSourceREST = function (request, response) {
var serverUrl = "crm.server.com"
var ODATA_ENDPOINT = "/ORGNAME/XRMServices/2011/OrganizationData.svc";
var ODATA_EntityCollection = "/ContactSet";
var strSelect = "$select=FullName,ParentCustomerId,ContactId"
var strFilter = "$filter=substringof('" + request.term + "',FullName) and StateCode/Value eq 0"
var URL = serverUrl + ODATA_ENDPOINT + ODATA_EntityCollection + "?" + strFilter + "&" + strSelect
//alert(URL);
$.ajax({
type: "GET",
contentType: "application/json",
datatype: "json",
async: false,
url: URL,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
XMLHttpRequest.setRequestHeader("Content-Type", "application/json")
},
success: function (data, textStatus, XmlHttpRequest) {
response($.map(data.d.results, function (item) {
return {
label: item.FullName + ' (' + item.ParentCustomerId["Name"] + ')',
value: item.FullName + ' (' + item.ParentCustomerId["Name"] + ')',
fullname: item.FullName,
ParentCustomerIdName: item.ParentCustomerId["Name"],
id: item.ContactId
}
}));
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("failure " + errorThrown);
return false;
}
});
}
Next is the knockout code (part of the view model) that is used to push the new contact guid into an observable array upon selecting the AutoCompleted contact
self.Attendees = ko.observableArray();
self.contact = function(fullname, firstname, lastname,ParentCustomerIdName, activitypartytype, guid) {
this.fullname = fullname;
this.firstname = firstname;
this.lastname = lastname;
this.ParentCustomerIdName = ParentCustomerIdName;
this.role = activitypartytype;
this.guid = guid;
};
self.addAttendee = function(fullname, firstname, lastname,ParentCustomerIdName, activitypartytype, guid) {
self.Attendees.push(new self.contact(fullname, firstname, lastname,ParentCustomerIdName, activitypartytype, guid));
return
};
And finally the knockout code to concatenate the GUIDs and put them in the hidden (original) field (Attendees).
ko.utils.arrayForEach(self.Attendees(), function(contact) {
total = total + contact.guid + ';'
});
total = total.substring(0, total.length - 1);
$('input[type=text][title="Attendees"]').val(total)
return total
});
Pretty complex, lots of different techniques bing used (knockout, jQuery, ajax). Hope it makes sense.