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.