i'm having a minor issue. I'm using REST/JS to populate a dropdown box, which requires first getting the lookup of a column in a list.
//Product Model Cascade
document.getElementById("productDD").onchange = function() {
var prod = this.options[document.getElementById("productDD").selectedIndex].text;
var select = document.getElementById("productModelDD");
$(select).empty();
var call2 = $.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists(guid'bb392616-24ee-47e2-9365-f17400348373')/Items", //the list
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
call2.done(function(data, textStatus, jqXHR) {
var select = document.getElementById("productModellDD");
for (index in data.d.results) {
var parent = data.d.results[index].AT_ARMATECproducts; //Lookup column
console.log("parent var: " + parent);
if (parent == prod) {
var op = document.createElement("option");
op.text = data.d.results[index].Title;
op.value = data.d.results[index].Title;
select.appendChild(op);
}
}
});
}
but the parent value is coming back as "undefined" and i've triple checked that this is the correct list. I've also tried .get_LookupValue() but it comes back as can't get it from an undefined field.
So how do you get the value of a lookup field via rest?
EDIT:
I have done select/expand in the REST Query but have come up with a 400 bad request error:
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists(guid'bb392616-24ee-47e2-9365-f17400348373')/items?$select=Title,AT_ARMATECproducts/Title&$expand=AT_ARMATECproducts/Title",
Where AT_ARMATECproducts is the lookup field in the ARMATEC Product Models List. AT_ARMATECproducts is a lookup to the ARMATEC Products list which grabs the titles.
So, it turns out the lookup list was under a different name for some reason, it the list it shows up as AT_ARMATECproducts but seems to actually be AT_Products1.
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists(guid'bb392616-24ee-47e2-9365-f17400348373')/items?$select=Title,AT_Products1/Title&$expand=AT_Products1/Title",
var parent = data.d.results[index].AT_Products1;
now returns [object object], when I tried .Titles it returned with the Titles of the List not the lookup list. And when I tried .AT_Products1.Title it returned with undefined.
When working with User/Lookup field values via SharePoint REST API it is important to differentiate between single-valued and multi-valued lookup fields.
Single-valued lookup fields
Assume Employee list with a single-valued lookup field Department
Then the query: /_api/web/lists/getbytitle('<list title>')/items returns lookup Id, for example:
getListItems(_spPageContextInfo.webAbsoluteUrl,'','Employees',
function(items){
if(items.length > 0)
console.log(items[0].DepartmentId); //returns LookupId
},
function(error){
console.log(error.responseText);
});
The query:
/_api/web/lists/getbytitle('Employees')/items?$select=Department/Title,Department/Id&$expand=Department
returns projected Department object as shown below:
getListItems(_spPageContextInfo.webAbsoluteUrl,'?$select=Department/Title,Department/Id&$expand=Department','Employees',
function(items){
if(items.length > 0)
console.log(items[0].Department.Title);
console.log(items[0].Department.Id);
},
function(error){
console.log(error.responseText);
});
Multi-valued lookup fields
Assume Employee list with a multi-valued lookup field Departments
Then the query: /_api/web/lists/getbytitle('<list title>')/items returns an array of lookup ids, for example:
getListItems(_spPageContextInfo.webAbsoluteUrl,'','Employees',
function(items){
if(items.length > 0)
console.log(items[0].DepartmentsId); //returns an array [LookupId1, LookupId1 .. LookupIdN]
},
function(error){
console.log(error.responseText);
});
The query:
/_api/web/lists/getbytitle('Employees')/items?$select=Departments/Title,Departments/Id&$expand=Departments
returns projected Departments array of objects as shown below:
getListItems(_spPageContextInfo.webAbsoluteUrl,'?$select=Departments/Title,Departments/Id&$expand=Departments','Employees',
function(items){
if(items.length > 0)
if(items[0].Departments.results.length > 0) {
console.log(items[0].Departments.results[0].Title);
console.log(items[0].Departments.results[0].Id);
}
},
function(error){
console.log(error.responseText);
});
SharePoint 2013 REST read operation function:
function getListItems(url, query, listName, success, failure) {
$.ajax({
url: url + "/_api/web/lists/getbytitle('" + listName + "')/items" + query,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
success(data.d.results);
},
error: function (data) {
failure(data);
}
});
}
Try
/_api/Web/Lists(guid'bb392616-24ee-47e2-9365-f17400348373')/items?$select=Title,AT_ARMATECproducts/Title&$expand=AT_ARMATECproducts"
as you endpoint
The expand query should only contain the title of the lookup column, and should not include the lookup field. Your select is fine, but the expand isn't.
below query finally worked for me
Merged is a calculated field in Cats list
Cat is a lookup field(which looks above Merged column) in the MainFlat list
"?$select=Title,number,Cat/Merged&$expand=Cat" +
"&$filter=Cat/Merged eq '"+Merged+"' "
https://sharepoint.stackexchange.com/a/152997/16880
Related
I have this requirement form business to Save Searches, allowing users to use saved search data and rerun the search. I have saved the search in database as JSON object. Problem is when users select already saved search via using Select - Dropdown, the form should pre populates all the selections that were saved with search. When I am trying to alert the key value within populate function - it always show key as 0 and value as whole JSON object. What am I missing here ?
Sample of returned JSON request from database looks like: {"affects":["153","503","537"],"suspect":["101","108"],"state":[],"zip_code":[],"analysis_date_max":["",""],"last_modified_date_min":["",""]}
Here is my existing code:
//START OF PROBLEM CODE
function populate(frm, data) {
var obj = $.parseJSON(data);
//alert (data);
//alert (frm);
alert (obj);
$.each(obj, function(key, value){
alert(key + ' is ' + value);
$('[name='+key+']', frm).val(value);
});
}
// END OF PROBLEM CODE
$('#search_dataselect').on('change', function()
{
getSearchData(this.value);
});
function getSearchData(search_id) {
if (!isNaN(parseInt(search_id))) {
$.ajax({
type: "GET",
url: "/index.cgi?p=json&t=SavedSearch&search_id="+search_id,
success: function(result){
var data = result;
populate('#formSearch',data);
},
});
}
return false;
}
It appears your data is not serialized.
Try this:
success: function(result) {
var data = JSON.stringify(result);
populate('#formSearch', data);
}
An example for using JSON.stringify()
https://jsfiddle.net/3u6mrft1/
For example I have a list call "shopping list", it has 2 columns.
1st Column Type is People or Groups(Allows Multiple People), the Column Name is "Customers".
2nd Column Type is string.
I can use ajax to post information to the normal SharePoint List, but just not to this Shopping List.
I know how to format the data for single user column, but not for multiple users column, The single user column is something like:
The column name is Customer, the data format should be:
item.CustomerID=1;
I have tried lots of way to format the data, but it is still the same. The server return 500 without any useful information.
Example formats below:
item.Customers = [1,2,3] //1,2,3 is the user id in SharePoint.
item.CustomersID=[1,2,3] //1,2,3 is the user id in SharePoint.
item.Customers=[{UserId:1},{UserId:2},{UserId:3}]
I can confirm that the javascript object has been stringify and the post request is correctly sent as I successfully added new items to the same list without filling in the Customers Column.
Can someone please advise me what is the correct format to post content to SharePoint 2010 REST API with multiple user columns.
In case of SharePoint 2010 REST Interface the proper payload for multi-valued user field should look like below:
'<MultiUserFieldName>': [
{
__metadata: {
"uri": "<WebUrl>/_vti_bin/listdata.svc/UserInformationList(<UserId>)"
}
}
]
where
MultiUserFieldName - user field name
WebUrl - absolute web url
UserId - user Id
JavaScript example
var webUrl = "http://contoso.intranet.com";
var listName = "ShoppingCart";
var properties = {
'Title': 'Item #123',
'Customers': createPayloadForMultiUserField(webUrl,[1,2,3])
};
createListItem(webUrl,listName,properties)
.done(function(data){
console.log('Item ' + data.d.Title + ' has been created');
})
.fail(function(error){
console.log(JSON.stringify(error));
});
where
function createListItem(webUrl,listName, itemProperties) {
return $.ajax({
url: webUrl + "/_vti_bin/listdata.svc/" + listName,
type: "POST",
processData: false,
contentType: "application/json;odata=verbose",
data: JSON.stringify(itemProperties),
headers: {
"Accept": "application/json;odata=verbose"
}
});
}
function createPayloadForMultiUserField(webUrl,userIds)
{
return userIds.map(function(id){
return {
__metadata: {
"uri": webUrl + "/_vti_bin/listdata.svc/UserInformationList(" + id + ")"
}
}
});
}
How do i get list items from different lists in SharePoint using javascript. Given that all my list are stored in an array. And I need to loop through the array and execute similar functions on each list.
function initializePage() {
listcollections.forEach(function (value, index) { // listcollections is the array that contains the list url for different lists
var listtitle = value.listTitle;
var siteUrl = value.siteURL;
getItemsWithCaml(siteUrl, listtitle,
function (camlItems) {
var listItemEnumerator = camlItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var EventsItem = new Events();
var listItem = listItemEnumerator.get_current();
EventsItem.eventTitle = listItem.get_item('Title');
EventsItem.eventDate = listItem.get_item('EventDate');
EventsItem.eventId = listItem.get_id();
EventsItem.eventSite = siteUrl;
EventsItem.eventList = listtitle;
EventsCollection.push(EventsItem);
}
},
function (sender, args) {
alert('An error occurred while retrieving list items:' + args.get_message());
});
})
};
function getItemsWithCaml(siteUrl, listtitle, header, success, error)
{
var hostWebContext = new SP.ClientContext(siteUrl);
var list = hostWebContext.get_web().get_lists().getByTitle(listtitle);
var caml = new SP.CamlQuery();
//Create the CAML that will return only items expiring today or later
caml.set_viewXml("<View><Query><Where><Geq><FieldRef Name=\'Expires\'/><Value Type=\'DateTime\'><Today /></Value></Geq></Where> </Query></View>");
var camlItems = list.getItems(caml);
hostWebContext.load(camlItems);
hostWebContext.executeQueryAsync(
function () {
success(camlItems);
},
error
);
};
//need to execute certain functions to format each list item
// I am not able to retrieve all list items in a single variable to be able to display data from all lists together
In the example below, I create a JavaScript object named ListDataCollection that contain a property Lists that is an array of objects.
Each of those contain a Url property whit the url of the lists I want to get the content.
Then I loop trough the array of objects and call the Sharepoint REST api for each Url.
Each time a call is complete :
I create a Data property on the current object with the data received
by the ajax call to the REST api.
I also update the current object Completed property to true.
Then I call a function named ifAllCompleted that check if all ajax calls are ended.
When all data is received, I log the word Completed on the browser console.
At this point, you have an array of objects. Each object contains the data of one Sharepoint list.
For example :
ListDataCollection.Lists[0].Data.d.results[0].Title
will contain the value of the Title Column of the first element in the first list.
If you want, you can merge all data in one array using the concat function in JavaScript.
Look at the 4 lines of code following the word Completed.
Hope this can help!
<script>
var ListDataCollection = {
Lists:[{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List1')/Items",
Completed:false
},{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List2')/Items",
Completed:false
},{
Url:"http://Url.Of.Your.Site.Collection/_api/web/lists/getbytitle('List3')/Items",
Completed:false
}]
};
function ifAllCompleted() {
for (var i=0;i<ListDataCollection.Lists.length;i++) {
if (!ListDataCollection.Lists[i].Completed) {
return false;
}
}
console.log('Completed');
var arrayOfAllData = ListDataCollection.Lists[0].Data.d.results;
arrayOfAllData = arrayOfAllData.concat(ListDataCollection.Lists[1].Data.d.results);
arrayOfAllData = arrayOfAllData.concat(ListDataCollection.Lists[2].Data.d.results);
console.log('Total elements : ' + arrayOfAllData.length);
}
$(document).ready(function(){
for (var x=0;x<ListDataCollection.Lists.length;x++) {
$.ajax({
url:ListDataCollection.Lists[x].Url,
indexValue:x,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data, status, xhr) {
ListDataCollection.Lists[this.indexValue].Data = data;
ListDataCollection.Lists[this.indexValue].Completed = true;
ifAllCompleted();
},
error: function (xhr, status, error) {
console.log('error');
}
});
}
});
</script>
i am using jquery to send json data that contains array of elements like this
$('#brand_category').click(function(event){
category = $("input:checkbox[name=category]:checked").map(function() {
return this.value;
}).get();
brand = $("input[type='radio']:checked").map(function() {
return this.value;
}).get();
parameter.push({
brand : brand,
category: category
});
var json = JSON.stringify(parameter)
$.ajax({
type: 'post',
url: "{% url 'seller_details' %}",
data: {'parameter[]' : json , csrfmiddlewaretoken:'{{csrf_token}}'},
success: function(data){
},
error:function (response, error){
}
});
and in the view i am collecting the data like this
brand_category = self.request.POST.get('parameter[]')
print brand_category
this prints the data as this
[{"brand":["spykar"],"category":["Women Clothing","Dresses"]},{"brand":["Madame"],"category":["Women Clothing","Dresses"]}]
then i tried to loop through the json like this
for list in list_data:
brand = list_data['brand']
print brand
categories = list_data['category']
print categories
but i am getting the error as this
list indices must be integers, not str
how can i loop through the json data to get the list of brands and categories?
Your outer loop is a list, and then you loop through each dictionary in the list. Also, you have to convert the string to a python object.
import json
brand_category = self.request.POST.get('parameter[]')
Lbrand_category = json.loads(brand_category)
for D in Lbrand_category:
brand,categories = D['brand'],D['category']
Note: if you want only the brand string, without the list, use:
brand,categories = D['brand'][0],D['category']
I recommend you this AJAX Request (Its more clear):
$('#brand_category').click( sendAjax );
function sendAjax()
{
var category = $("input:checkbox[name='category']:checked").val();
var brand = $("input[type='radio']:checked").val();
var data = { "category" : category, "brand" : brand, "csrfmiddlewaretoken" : '{{csrf_token}}' }
$.ajax({
type: 'post',
url: "{% url 'seller_details' %}",
data: data,
success: function(data)
{
//console.log(data) // Print the response of Django or see this in "Network" request, F12 Chrome
},
error:function (response, error)
{
}
});
}
View:
category = request.POST['category']
print category
brand = request.POST['brand']
print brand
List data of brands in JavaScript:
var data = {} //This is a empty object named data
data.brans = [];
and then you need create a for select all brands
for ("list of brands"){
brand_name = logic
data.brands.push(brand_name)
} //This is only a idea
I have a problem which is proving to be harder to find an answer for than I imagined. I am using AJAX to update the select options based on a response from another select box. I am able to correctly retrieve the right list of objects, serialized as json, but I can't access any of the field values of the object.
View:
def choose_group(request):
team_id = request.POST['team_id']
groups = WorkoutGroup.objects.filter(team_id=team_id)
data = serializers.serialize('json', groups)
return HttpResponse(data, content_type='application/json')
Javascript/jQuery:
$('#team').on('change', function(){
var team_id = $(this).val();
$.ajax({
type: 'POST',
url: '/create_workout/choose_group/',
dataType: 'json',
async: true,
data: { csrfmiddlewaretoken:'{{ csrf_token }}', team_id: team_id },
success: function(data) {
var groups = $('#group');
$(groups).children().not(':first').remove();
if (data.length >= 1){
$.each(data, function(group){
$(groups).append('<option value=' + group['fields']['id'] + '>' + group['fields']['group_name'] + '</option>');
});
}
}
});
})
I get an error with all the ways I've tried to access the fields of each object (such as the id and group_name of the objects, as defined in the model). The error is 'cannot read property of undefined'.
EDIT:
I have also tried just creating a ValueQuerySet and dumping it using simplejson, but I still cannot access any fields within, just 'undefined'. Also, if I alert through each group, I get just the index of the iteration within the group list.
New View:
def choose_group(request):
team_id = request.POST['team_id']
groups = WorkoutGroup.objects.filter(team_id=team_id).values('id','group_name')
#data = serializers.serialize('json', groups)
return HttpResponse(simplejson.dumps(list(groups)), content_type='application/json')
and my Javascript now looks like this:
$('#team').on('change', function(){
var team_id = $(this).val();
$.ajax({
type: 'POST',
url: '/create_workout/choose_group/',
dataType: 'json',
async: true,
data: { csrfmiddlewaretoken:'{{ csrf_token }}', team_id: team_id },
success: function(groups_list) {
var groups = $('#group');
$(groups).children().not(':first').remove();
if (groups_list.length >= 1){
//json = JSON.parse(data);
$.each(groups_list, function(group){
alert(group)
$(groups).append('<option value=' + group.pk + '>' + group.fields.group_name + '</option>');
});
}
}
});
})
Accessing the serialized django object
To access the serialized django object you need to first parse the data variable like this:
var obj = JSON.parse(data);
And then you can access the fields of each object Individually like this:
// for the first object
obj[0]['fields']['id'] // or obj[0].fields.id
obj[0]['fields']['group_name'] // or obj[0].fields.group_name
// for the second object
obj[1]['fields']['id'] // or obj[1].fields.id
obj[1]['fields']['group_name'] // or obj[1].fields.group_name
// and so on...
In your case you can do this:
$.each(obj, function(index){ // for each object
$(groups).append('<option value=' + obj[index]['fields']['id'] + '>'+ obj[index]['fields']['group_name'] + '</option>');
});