Search code examples
sharepointsharepoint-clientobject

Update ProjectedField with JOIN in Sharepoint using Javascript client object model


Suppose I have 2 Lists: Teams and Employees. Each team has a number of employees:

Teams
  ID
  Name

Employees
  ID
  Name
  TeamID (foreign key of Teams)

If I created a Join query of Employees LEFT JOIN Teams, could I then set_item and update the Name field in Teams?

var ctx = SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle('Employees');

var queryText = 
"<View>" +
  "<Query></Query>" +
  "<ProjectedFields>" +
    "<Field Name='TeamName' Type='Lookup' List='Team' ShowField='Name' />" +
  "</ProjectedFields>" +
  "<Joins>" +
    "<Join Type='INNER' ListAlias='Team'>" +
      "<Eq>" +
        "<FieldRef Name='TeamID' RefType='Id'/>" +
        "<FieldRef List='Team' Name='ID'/>" +
      "</Eq>" +
    "</Join>" +
  "</Joins>" +
  "<ViewFields>" +
    "<FieldRef Name='TeamName'/>" + 
  "</ViewFields>" +
"</View>";   

var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml(queryText);

var listItemsCollection = list.getItems(camlQuery);
ctx.executeQueryAsync(onSuccess, onError);

And then, update the TeamName field:

var first = listItemsCollection.get_data()[0];
first.set_item("TeamName", "something");
first.update();

ctx.executeQueryAsync(onSuccess, onError);

Is this supported? (I currently have not way of trying this)

If not, what could be the alternative?


Solution

  • No, only those fields that contains list item could be updated. But you could consider the following approach for updating projected fields.

    Since projected fields are returned as lookup values, you could retrieve projected list item and update it's properties as demonstrated below:

    var listTitle = 'Employees';
    var joinListTitle = 'Teams' 
    var joinFieldName = 'TeamID';
    var projectedFields = ['Name'];
    
    
    getListItems(listTitle,joinListTitle,joinFieldName,projectedFields,
      function(items){
    
         var item = items.get_data()[0]; //get first item
         var itemId = item.get_item('TeamsName').get_lookupId(); //get projected list item id
         var propertiesToUpdate = {'Name': 'New Team Name'};
    
         updateListItem(joinListTitle,itemId,propertiesToUpdate,function(item){
            console.log('List Item has been updated');
         },
         logError);
    
    
      },
     logError);
    

    where

    function createJoinQuery(joinListTitle,joinFieldName,projectedFields,joinType)
    {
       var queryText = 
       "<View>" +
           "<Query/>" +
             "<ProjectedFields>";
        for(var idx in projectedFields) {
            queryText += String.format("<Field Name='{0}{1}' Type='Lookup' List='{0}' ShowField='{1}' />",joinListTitle,projectedFields[idx]);
        }
        queryText +=
             "</ProjectedFields>" +
             "<Joins>" +
                 "<Join Type='{2}' ListAlias='{0}'>" +
                    "<Eq>" +
                      "<FieldRef Name='{1}' RefType='Id'/>" +
                      "<FieldRef List='{0}' Name='ID'/>" +
                    "</Eq>" +
                 "</Join>" +
             "</Joins>" +
        "</View>";   
        var qry = new SP.CamlQuery();
        qry.set_viewXml(String.format(queryText,joinListTitle,joinFieldName,joinType));
        return qry;
    }
    
    function getListItems(listTitle,joinListTitle,joinFieldName,projectedFields,success,error)
    { 
       var ctx = SP.ClientContext.get_current();
       var web = ctx.get_web();
       var list =  web.get_lists().getByTitle(listTitle);
       var items = list.getItems(createJoinQuery(joinListTitle,joinFieldName,projectedFields,'INNER'));
    
       ctx.load(items);
       ctx.executeQueryAsync(
         function() {
           success(items);  
         },
         error
       );
    }
    
    
    
    function updateListItem(listTitle,itemId, propertiesToUpdate,success,error)
    {
        var ctx = SP.ClientContext.get_current();
        var web = ctx.get_web();
        var list =  web.get_lists().getByTitle(listTitle);
        var listItem = list.getItemById(itemId);
        for(var name in propertiesToUpdate) {
            listItem.set_item(name,propertiesToUpdate[name]);   
        }
        listItem.update();
        ctx.executeQueryAsync(function() {
           success(listItem);
        },error);
    }