Monday, 1 August 2016

SharePoint Online: How do I run a Javascript update with a lookup on a NewForm.aspx or EditForm.aspx?

The requirement I faced with my SharePoint online project was to update fields on the new and edit forms once an item had been selected. The main problem was that the update required a lookup to existing data for each item in a multi select box.

The obvious solution was to use PreSaveAction in a Script Editor webpart,
The script looked something like this:

<script type="text/javascript" src="//code.jquery.com/jquery-1.11.2.min.js"></script>         
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.02/jquery.SPServices.min.js"></script>
<script type="text/javascript">
var $j = jQuery.noConflict(); 
function PreSaveAction() { 
function SetValue(onComplete)
{
// clear the target item
$("textarea[id*='MyTargetField']").val('');
var listTitle = 'MyLookupList';
var ids = [];
                // get the items from the selection result
$("select[id*='_SelectResult']").children().each(function() {ids.push($(this).val())});

var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var list = web.get_lists().getByTitle(listTitle);
var result = []; //for storing items 
ids.forEach(function(id){
var item = list.getItemById(id);
ctx.load(item, ['Title', 'Id', 'MyLookupColumn']);

result.push(item);
});

ctx.executeQueryAsync(
function() { 
                        // update the text area with the required field (comma seperated)
result.forEach(function(x){
$("textarea[id*='MyTargetField']").val($("textarea[id*='MyTargetField']").val() + x.get_item('MyLookupColumn') + ','); 
})
                        // call a method so that we can return True and save the data (THIS DID NOT WORK)
onComplete();
 },
 function(sender,args){console.log(args.get_message());} 
); 
}

SetValue(
function()
{
                        // remove the trailing comma  
$("textarea[id*='MyTargetField']").val($("textarea[id*='MyTargetField']").val().substring(0, $("textarea[id*='MyTargetField']").val().length - 1));
return true;
}
)
}

</script>      

The corresponding field was updated (yay!), but since the method did not return 'True', no data was persisted (bummer!).

A new approach was required. My solution is not optimal, but functional.
I created a listener to the DOMNodeInserted and DOMNodeRemoved events and run my update script.

$('#s4-workspace').bind('DOMNodeInserted DOMNodeRemoved', function() {
UpdateCodes();
});

My final code looked as follows:

<script type="text/javascript" src="//code.jquery.com/jquery-1.11.2.min.js"></script>         
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2014.02/jquery.SPServices.min.js"></script>

<script type="text/javascript">
function UpdateCodes()
{
var listTitle = 'MyLookupList';
var ids = [];
$("select[id*='_SelectResult']").children().each(function() {ids.push($(this).val())});
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var list = web.get_lists().getByTitle(listTitle);
var result = []; //for storing items 
ids.forEach(function(id){
var item = list.getItemById(id);
ctx.load(item, ['Title', 'Id', 'MyLookupColumn']);
result.push(item);
});

ctx.executeQueryAsync(
function() { 
$("textarea[id*='MyTargetField']").val('');

result.forEach(function(x){
$("textarea[id*='MyTargetField']").val($("textarea[id*='MyTargetField']").val() + x.get_item('MyLookupColumn') + ','); 
})
$("textarea[id*='MyTargetField']").val($("textarea[id*='MyTargetField']").val().substring(0, $("textarea[id*='MyTargetField']").val().length - 1));
},
function(sender,args){console.log(args.get_message());} 
); 
}

$('#s4-workspace').bind('DOMNodeInserted DOMNodeRemoved', function() {
UpdateCodes();
});

</script>      


No comments:

Post a comment