Copying selected items data from one list to another

May 20, 2011 at 3:28 PM

I am creating a Delegation of Authority system in which I have a list of Activities that a user in a Role is allowed to peform. i.,e the Division Managers can approve Purchase Requistions, Travel Requests and Tuition Reimbursements. I want to display these activities, allow the user to select one (or more of them) and then initiate a workflow that will 1) prompt the user for the name of the person to whom they are delegating their authority for the selected activity, 2) copy the selected activities to another list (that will store the start/end dates for the delegation as well as the delegates name) and 3) create an email containing the titles of the selected activities.

I can do this for one activity, but I can't figure out how to identify all of the items from the list that were selected. Can anyone give me some advice?

TIA
Dean

Coordinator
May 20, 2011 at 5:23 PM

Dean:

It sounds like you are working in SharePoint 2010 and that you're having trouble getting the jQuery selector right for the selected items in a view. Is that right?

M.

May 20, 2011 at 6:17 PM

Yes. that is correct

 

Coordinator
May 23, 2011 at 12:55 PM

Something like this ought to get you close:

$("td.ms-vb-itmcbx input:checked")

M.

May 24, 2011 at 1:05 PM

Mark, I'm trying to display a list on page so that users can check several items and then i am going to copy the selected the items to another list (along with some extra data) but before I can even do the copy step I am getting the error message, Expected Hex 0x in {0xdddddd, etc} when i use the following. Any idea what I might be doing wrong?,

<script type="text/javascript">

var camlQuery="<Query><Where><Eq><FieldRef Name='Role' /><Value Type='Text'>President</Value></Eq></Where></Query>"
$(document).ready(function() {
  $().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "Authorities",
    CAMLQuery:camlQuery,
    completefunc: function (xData, Status) {
      $("td.ms-vb-itmcbx input:checked").each(function() {
        var liHtml = "<li>" + $(this).attr("ows_Category")  + "--" +$(this).attr("ows_Activity") + "--" +$(this).attr("ows_Role")
           + "--" +$(this).attr("ows_Responsibility") +  "</li>";
        $("#tasksUL").append(liHtml);
      });
    }
  });
});

</script>
<ul id="tasksUL"/>
<WebPartPages:XsltListViewWebPart runat="server" IsIncluded="True" GhostedXslLink="main.xsl" FrameType="None" NoDefaultStyle="TRUE" ViewFlag="8" Title="Authorities" PageType="PAGE_NORMALVIEW" ListName="{9188743B-29E1-478C-8E49-75E23E35C7CE}" Default="FALSE" DisplayName="Authorities" __markuptype="vsattributemarkup" __WebPartId="{82DC28DE-C739-4175-AEBA-C595C03317B2}" id="g_82dc28de_c739_4175_aeba_c595c03317b2" viewcontenttypeid="0x" __designer:customxsl="fldtypes_Ratings.xsl" __AllowXSLTEditing="true" WebPart="true" Height="" Width="">
<XmlDefinition>
 <View Name="{49239F6D-C8B0-475C-9F9B-073F837D4E7D}" MobileView="TRUE" Type="HTML" DisplayName="All Items" Url="/corp/Policies/DelegateAuthority/Lists/Authorities/AllItems.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/generic.png">
  <Query>
   <Where>
    <Eq>
     <FieldRef Name="Role"/>
     <Value Type="Text">President</Value>
    </Eq>
   </Where>
  </Query>
  <ViewFields>
   <FieldRef Name="Category"/>
   <FieldRef Name="Activity"/>
   <FieldRef Name="Role"/>
   <FieldRef Name="Responsibility"/>
  </ViewFields>
  <RowLimit Paged="TRUE">30</RowLimit>
  <Aggregations Value="Off"/>
  <Toolbar Type="Standard"/>
 </View>
</XmlDefinition>

Coordinator
May 24, 2011 at 1:21 PM

You're doing an apples and oranges thing. You're trying to use the  $("td.ms-vb-itmcbx input:checked") selector on the XML returned from the GetListItems operation. That selector is what I think you need (not validated) to figure out which rows are checked in a SharePoint 2010 list view.

M.

Coordinator
May 25, 2011 at 8:03 PM

Dean:

Sorry; I left you a little in limbo here. Have you made progress? More questions?

I saw your post over at the Microsoft SharePoint Designer Team Blog, (comment on the Creating a SharePoint 2010 Workflow using SPD 2010 and Visio 2010: How-To & FAQ post) and responded with how great SPServices would be for what you're doing. Somehow that comment hasn't been approved. ;+)

M.

May 26, 2011 at 7:36 AM

Thanks for the follow up. I have not made much progress because I'm totally confused about what I should be doing, i don't have much experience in this area and feel like i'm on the right track but i'm not quite sure of the logical flow of the code.  I have not been able to find any examples that use the syntax you suggested. Could you please provide me with a more detailed explanation of your recommendation.

TIA

Dean

Coordinator
May 26, 2011 at 11:33 AM

Dean:

You're probably not going to find a great example out there. What you're trying to do is fairly unique.

Here's the flow of what you want to do, as I understand it:

  • Determine which items in the list view are checked. What do you want to use to trigger this?
  • Get the list items from list 1 using GetListItems.
  • Create new list items in list 2 which match the list 1 items. How should they match? Exact copies? Where does the extra data come from?

So the code will something like:

$("td.ms-vb-itmcbx input:checked").each(function() {

  // Get the selected item
  $().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "Authorities",
    CAMLQuery:camlQuery,
    completefunc: function (xData, Status) {
       // For the retreived item (you mgiht want to grab more than one at a time)
       $(xData.responseXML).find("[nodeName='z:row']").each(function() { 

         $().SPServices({
           operation: "UpdateListItems",
           async: false,
           listName: "Authorities",
           batch: // The batch command to tell UpdateListItems what to do

           // etc.


      });
    }
  });
});

M.

May 26, 2011 at 5:23 PM

Marc, thank for the additional advice. i'm thinking that I need to add a "Delegate Selected Items" button to my page, i've seen some articles about adding a button to the Ribbon, but that seems like a lot of extra work, how do you go about making this decision for your clients?.

The extra data will be coming from another list that contains 2 fields (DelegateTo (a Person field) and End Date). I'm thinking that the user will fill in those values, then check the boxes for the items they want to delegate, then click on the button, the code will get the DelegateTo and EndDate values, put them into variables, identify the selected items (get the Title and Responsibility field values from the selected row) then create a new item and fill in the fields with the data in the variables. Does this make sense to you? am I on the right track?

BTW, i listened to your podcast interview with Jeremy Thacke on my way into the office this am.

Coordinator
May 26, 2011 at 5:51 PM

That old podcast? I wonder if I still believe the same things. Probably!

I think you're on the right track. Assuming that the DelegateTo and End Date values are selected in the page, you'll need a little script to grab those values from their elements as well.

Keep in mind that you can grab columns for the selected items with the GetListItems call, even if they aren't displayed in the view.

M.

Jun 4, 2011 at 12:09 PM

I have a page with listview web part and the following javascript. all of the rows from the Authorities list are getting copied to the Delegations list instead of just the selected items. Could someone please tell me what i'm doing wrong. Thanks

<script type="text/javascript">.
//$(document).ready(function(){
// alert ("jQuery");
//});

function delegateActivities(){
 var camlQuery = "";
 var endDate = '6/13/2011 00:00:00';
 //var reviewPeriod = "4";
 //var delegator = "gross, dean";
 //var delegator = $()SPServices.SPGetCurrentUser({
 // fieldName:'ID',
 // debug:false
 //});
 //var delegate = "smith, joe";
 alert (delegator);
 //alert (reviewPeriod);
 $("td.ms-vb-itmcbx input:checked").each(function() {
 // Get the selected item
 
  $().SPServices({
   operation: "GetListItems",
   async: false,
   listName: "Authorities",
   CAMLQuery:camlQuery,
   completefunc: function (xData, Status) {
  // For the retreived item (you might want to grab more than one at a time)
    $(xData.responseXML).find("[nodeName='z:row']").each(function() {
     var strTitle = $(this).attr("ows_Activity");

     $().SPServices({
      operation: "UpdateListItems",
      async: false,
      listName: "Delegations",
      //batch: The batch command to tell UpdateListItems what to do
      batchCmd: "New",
      valuepairs: [["Activity", strTitle]],
      completefunc: function(xData, Status) {
       //alert("completed");
      }
     });
    });
   }
  });
 });
}
</script>

Coordinator
Jun 4, 2011 at 3:17 PM

Dean:

Your GetListItems call isn't filtered at all, so you're getting every item in the list. You need to filter for the checked item in the .each loop.

Looking at the code, I would expect that you would get one new item in the Delegates list for every item in the Authorities list times the number of items checked.

M.

Jun 5, 2011 at 12:12 PM

that makes sense, I was thinking that the td.ms-v-itmcbx input:checked statement was providing the filtering, but obviously this is not happening because this statement is only identifying how many times the function should run.  I'm used to working in Sql server and i'm trying to adapt my experience with Where clauses and data sets to this environment so i'm still a little bit confused about the flow of operations and when I can do operations on an entire set/list and when i need to go row by row. You are advising me to filter in the .each loop, does this mean that I do NOT need to create a camlquery that filters for the id of the item and that i need to modify the find parameters to only find the id of the selected checkboxes?

TIA

Dean

Coordinator
Jun 5, 2011 at 12:54 PM

Dean:

The

$("td.ms-vb-itmcbx input:checked")

 selector is giving you a jQuery array of objects, each of which represents one checked row. However, in the GetListItems call, you're not passing anything from that array as part of a CAMLQuery option, so you're just getting all of the items back. You need the 

CAMLQuery:camlQuery,

line, but you need to include the filter. I can't tell you exactly what it should look like, but you need to figure out where in the checked row you can find the ID and then set the CAMLQuery to something like this:

CAMLQuery: "<Query><Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>" + thisID + "</Value></Eq></Where></Query>",

where thisID is the ID for the currently checked row.

M.

Jun 6, 2011 at 2:29 PM

Ok, its monday morning and I think i'm on the right track, but i'm still having a problem getting the ID from the row in the list view. I thought that i would be able to get it from ows_ID, but my alert box is not showing anything. I have tried several other fields and i'm always getting nothing. Apparently, using the $(this).attr method is not the correct technique. could someone please share their wisdom and educate this struggling "programmer".

 

function delegateActivities(){
 var camlQuery = "";
 var endDate = '6/13/2011 00:00:00';
 //var reviewPeriod = "4";
 var delegator = "gross, dean";
 //var delegator = $()SPServices.SPGetCurrentUser({
 // fieldName:'ID',
 // debug:false
 //});
 //var delegate = "smith, joe";
 //alert (delegator);
 //alert (reviewPeriod);

 $("td.ms-vb-itmcbx input:checked").each(function() {
 // Get the selected item
 var thisID = 24;
 alert ("thisID hard coded-"+thisID);
 var thisID1 = $(this).find("nth-child(3)").text();
 alert ("Nth child3-"+ thisID1);
     var thisID2 = $(this).attr("Id");
     alert ("Id-"+thisID2);
     var thisID3 = $(this).attr("ows_ID");
     alert ("ows_ID-"+thisID3);
 var thisID4 = $(this).find("ID").text();
 alert ("Find ID-"+ thisID4);
     var thisID5 = $(this).attr("ID");
     alert ("ID-"+thisID5);

     var thisID6 = $(this).attr("ows_Title");
     alert ("ows_Title-"+thisID6);
    
  $().SPServices({
   operation: "GetListItems",
   async: false,
   listName: "Authorities",
   CAMLViewFields:"<ViewFields><FieldRef Name='Category' /><FieldRef Name='Activity' /><FieldRef Name='Role' /><FieldRef Name='Responsibility' /></ViewFields>",
   CAMLQuery:"<Query><Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>"+ thisID +"</Value></Eq></Where></Query>",
   completefunc: function (xData, Status){
   //alert(xData.responseXML.xml);
   alert ("CAMLQuery" + CAMLQuery);
  // For the retreived item (you might want to grab more than one at a time)
    $(xData.responseXML).find("[nodeName='z:row']").each(function() {
     var strTitle = $(this).attr("ows_Activity");
     //alert ("ows_ID-"+ $(this).attr("ows_ID"));
     //alert ("Id-"+ $(this).attr("Id"));
     //alert ("iid-"+ $(this).attr("iid"));
  
     $().SPServices({
      operation: "UpdateListItems",
      async: false,
      listName: "Delegations",
      //batch: The batch command to tell UpdateListItems what to do
      batchCmd: "New",
      valuepairs: [["Activity", strTitle]],
      completefunc: function(xData, Status) {
       alert("completed");
      }
     });
    });
   }
  });
 });
}

Coordinator
Jun 6, 2011 at 2:36 PM

Dean:

ows_ID won't be defined because there's nothing in the row with that attribute. Somewhere in the item's row, there will be something which contains the ID.

In a list view which I just checked, there's a link on the Title which looks something like this:

<a onclick="EditLink2(this,82);return false;" onfocus="OnLink(this)" href="https://servername/_layouts/listform.aspx?PageType=4&ListId={9533703C-9008-44D0-BA36-2CF8F6E51401}&ID=1&ContentTypeID=0x010400F5956D69D8379740A4ABA6CB7E1FFAF00100EFC947408454A34E946FB2FCFB449CCB" target="_self">

Note the 'ID=1' in the href. That's one possible way to get at the ID.

Your specific view may be different, so you'll need to find a similar place to grab the ID.

M.

Jun 6, 2011 at 3:05 PM

I added the ID field from the list into the listview on the page expecting to be able to see the same value in my alert by using $this.attr("ID") but this is coming back blank. is there something different that i need to do because it is an XSLTListviewwebpart?

 

Jun 6, 2011 at 9:24 PM

Making progress, but have a new issue. In the code below, i am able to successfully copy a field from Authorities list to my Delegations list, but when i try to add data in the aditional fields, it does not work. The Delegate field in my Authorities list is a Person column and I though that by using the split function i would be able to copy it into a text field, but nothing happens. Am I off base?

Also, when I try to update the EndDate field in the Delegatoin list nothing happens.

I getting my Delegate and EndDate values from another list but i don't undestand why this would cause a problem.

Any advice would be greatly appreciated.

function delegateActivities(){
 var endDate = '6/13/2011 00:00:00';
 var delegate;
 var ctx = SP.ClientContext.get_current();
 var items= SP.ListOperation.Selection.getSelectedItems(ctx);
 var myItems = '';
 var k;
 var thisID = 24;
 
 $(document).ready(function() {
  $().SPServices({
     operation: "GetListItems",
     async: false,
     listName: "DelegateAssignmentInput",
     CAMLViewFields: "<ViewFields><FieldRef Name='Delegate' /><FieldRef Name='EndDate' /></ViewFields>",
     completefunc: function (xData, Status) {
        $(xData.responseXML).find("[nodeName='z:row']").each(function() {
          var delegate = $(this).attr("ows_Delegate").split(";#")[1];
          var endDate = $(this).attr("ows_EndDate");
          alert ("Delegate-"+ delegate);
          alert ("endDate-"+ endDate);
    });
   }
  });
 });

 for (k in items)
 {
   //myItems+= '|'+ items[k].id;
   thisID = items[k].id;
 // Get the selected item
  alert ("thisID -"+ thisID);
       
  $().SPServices({
   operation: "GetListItems",
   async: false,
   listName: "Authorities",
   CAMLViewFields:"<ViewFields><FieldRef Name='Category' /><FieldRef Name='Activity' /><FieldRef Name='Role' /><FieldRef Name='Responsibility' /></ViewFields>",
   CAMLQuery:"<Query><Where><Eq><FieldRef Name='ID' /><Value Type='Counter'>"+ thisID +"</Value></Eq></Where></Query>",
   completefunc: function (xData, Status){
   //alert(xData.responseXML.xml);
   //alert ("CAMLQuery" + CAMLQuery);
   // For the retreived item (you might want to grab more than one at a time)
    $(xData.responseXML).find("[nodeName='z:row']").each(function() {
     var strTitle = $(this).attr("ows_Activity");
     $().SPServices({
      operation: "UpdateListItems",
      async: false,
      listName: "Delegations",
      //batch: The batch command to tell UpdateListItems what to do
      batchCmd: "New",
      valuepairs: [["Activity", strTitle],["Delegate", delegate]],
      completefunc: function(xData, Status) {
      // alert("completed");
      }
     });
    });
   }
  });
 };
//alert ("myItems-" +myItems);
};

Jun 7, 2011 at 6:59 PM

Success, i was redefining my variable within the GetListItems function and I have it working now. Thanks for your help.

Dean

Coordinator
Jun 8, 2011 at 1:17 AM

Excellent! And you're welcome.

M.