set taxonomy field multiple values - javascript

I'm creating a sharepoint hosted app which is based on javascript only. I wanted to update a multivalue taxonomy field in a list so I wrote this function which didn't work. there is a very little support for javascript csom online.
var list = context.get_web().get_lists().getByTitle('Company');
var item = list.getItemById(2);
var field = list.get_fields().getByInternalNameOrTitle("Departments");
var taxField = context.castTo(field, SP.Taxonomy.TaxonomyField);
var terms = new SP.Taxonomy.TaxonomyFieldValueCollection(context,
'Unit 1|5bf47d1f-d890-49d1-a844-85628ca508fd;#Unit 4|334ad23d-d2d8-4acb-ab09-38d2bacb97d4',
taxField);
taxField.setFieldValueByValueCollection(item, terms);
item.update();
context.load(taxField);
context.executeQueryAsync(
function() {
console.log('field updated');
});
I also used this code
var list = context.get_web().get_lists().getByTitle('Company');
var item = list.getItemById(2);
item.set_item('Departments', 'Unit 1|5bf47d1f-d890-49d1-a844-85628ca508fd;Unit 4|334ad23d-d2d8-4acb-ab09-38d2bacb97d4');
item.update();
context.executeQueryAsync(
function() {
console.log('field updated');
});

You must include a fake wssid (lookup id) prefix to the value. Below is a code I use to set a multiple value term field from jsom in the app model. This works.
function SetManagedMetaDataField() {
appweburl = decodeURIComponent(getQueryStringParameter('SPAppWebUrl'));
hostweburl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));
context = new SP.ClientContext(appweburl);
factory = new SP.ProxyWebRequestExecutorFactory(appweburl);
context.set_webRequestExecutorFactory(factory);
appContextSite = new SP.AppContextSite(context, hostweburl);
var list = appContextSite.get_web().get_lists().getByTitle('Documents');
var item = list.getItemById(5);
var field = list.get_fields().getByInternalNameOrTitle("Cars");
var taxField = context.castTo(field, SP.Taxonomy.TaxonomyField);
var terms = new SP.Taxonomy.TaxonomyFieldValueCollection(context,
'-1;#ATS|9f3e8e20-593b-471d-a145-81ff8664fd96;#-1;#CTS|8b18f6df-22be-4548-92b4-8f240d8fbfe5',
taxField);
taxField.setFieldValueByValueCollection(item, terms);
item.update();
context.load(taxField);
context.executeQueryAsync(
function () {
alert('field updated');
}, function (sender,args) {
alert(args.get_message() + '\n' + args.get_stackTrace());
});
}

Related

array[oListItem.id] has values but array[6], array[7] etc. are undefined

I retrieve values from a SharePoint list and put them in an array itemprices.
Using console.log("Price of list item at is:" + itemprices[oListItem.id]); will print out the values of the array, but using console.log("itemprices 5: " + itemprices[5]); tells me that they are undefined:
This is the code I used:
var itemprices = [];
// Gets values from Catalogue list; but they can't be used in the Position list because of different formats
function retrieveListItems() {
var clientContext = new SP.ClientContext.get_current();
catalogueList = clientContext.get_web().get_lists().getByTitle('Catalog');
var camlQuery = new SP.CamlQuery(); // initiate the query object
camlQuery.set_viewXml('<View><Query><Where><In><FieldRef Name=\'ID\'/><Values><Value Type=\'Number\'>5</Value><Value Type=\'Number\'>6</Value><Value Type=\'Number\'>7</Value></Values></In></Where></Query></View>');
itemColl = catalogueList.getItems(camlQuery);
// returns the item collection based on the query
context.load(itemColl);
context.executeQueryAsync(retrieveListItemsSuccess, retrieveListItemsFail);
}
function retrieveListItemsSuccess() {
var listItemEnumerator = itemColl.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
itemprices[oListItem.id] = oListItem.get_item('Preis');
console.log("itemprices 5: " + itemprices[5]);
console.log("itemprices 6: " + itemprices[6]);
console.log("itemprices 7: " + itemprices[7]);
console.log("Price of list item at is:" + itemprices[oListItem.id]);
}
}
// This function is executed if the above call fails
function retrieveListItemsFail(sender, args) {
alert('Failed to get list items. Error:' + args.get_message());
}
I don't know if this is a JavaScript issue or a SharePoint issue. What am I doing wrong?
Firstly, please use the right ClientContext object, in the code snippet above, it should be clientContext rather than context and if you want to populate field values into an array, try to use array.push, here is the modified code snippet for your reference:
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(retrieveListItems, 'sp.js');
var itemprices = [];
// Gets values from Catalogue list; but they can't be used in the Position list because of different formats
function retrieveListItems() {
var clientContext = new SP.ClientContext.get_current();
catalogueList = clientContext.get_web().get_lists().getByTitle('Companies');
var camlQuery = new SP.CamlQuery(); // initiate the query object
camlQuery.set_viewXml('<View><Query><Where><In><FieldRef Name=\'ID\'/><Values><Value Type=\'Number\'>5</Value><Value Type=\'Number\'>6</Value><Value Type=\'Number\'>7</Value></Values></In></Where></Query></View>');
itemColl = catalogueList.getItems(camlQuery);
// returns the item collection based on the query
clientContext.load(itemColl);
clientContext.executeQueryAsync(retrieveListItemsSuccess, retrieveListItemsFail);
}
function retrieveListItemsSuccess() {
var listItemEnumerator = itemColl.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
itemprices.push(oListItem.get_item('Title'));
}
console.log(itemprices);
}
// This function is executed if the above call fails
function retrieveListItemsFail(sender, args) {
alert('Failed to get list items. Error:' + args.get_message());
}
</script>
This is my list data:
This is the array from Console:
You can just use this function:
itemprices.map(itemPrice => console.log(itemPrice))

How to retrieve multi-value Taxonomy Field from term store SharePoint online

I am trying to retrieve terms from term store using JavaScript, it work just a fine with this code:
Get the label of single taxonomy field:
var fieldValue = item.get_item("FieldName");
var fieldLabel = fieldValue.Label;
I have one issue to retrieve labels of a multi-value Taxonomy Field?
I've tried this
var fieldValue = item.get_item("FieldName");
var taxEnumerator = fieldValue.getEnumerator();
while(taxEnumerator.moveNext()){
var currentTerm = taxEnumerator.get_current();
var label = currentTerm.Label;
// do something with the label here
}
But it doesn't work
Most likely you are getting this error since sp.taxonomy.js library has not been loaded and in that case taxonomy field value is returned as "lightweight" object (not of SP.Taxonomy.TaxonomyFieldValueCollection object type).
Option 1 (recommended): getting getting multiple taxonomy field values with sp.taxonomy library
First of all, I would recommend this approach since SP.Taxonomy namespace provides not only a standard way for dealing with taxonomy field values but also a way of working with Managed Metadata API via JSOM.
The following example shows how to:
ensure sp.taxonomy.js library has been loaded
get multiple taxonomy field value which represents
SP.Taxonomy.TaxonomyFieldValueCollection object
Example:
SP.SOD.registerSod('sp.taxonomy.js', SP.Utilities.Utility.getLayoutsPageUrl('sp.taxonomy.js'));
SP.SOD.executeFunc('sp.taxonomy.js', 'SP.Taxonomy.TaxonomySession', function () {
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
var item = list.getItemById(itemId);
ctx.load(item);
ctx.executeQueryAsync(
function(){
var fieldVal = item.get_item(fieldName);
for(var i = 0; i < fieldVal.get_count(); i++) {
var label = fieldVal.get_item(i).get_label();
var guid = fieldVal.get_item(i).get_termGuid();
//...
}
},
function(sender,args){
console.log(args.get_message());
});
});
Option 2: getting multiple taxonomy field values without sp.taxonomy.js library loaded
When sp.taxonomy library is not loaded, taxonomy field value could still be retrieved via _Child_Items_ property as demonstrated below:
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
var item = list.getItemById(itemId);
ctx.load(item);
ctx.executeQueryAsync(
function(){
var fieldVal = item.get_item(fieldName)._Child_Items_;
for(var i = 0; i < fieldVal.length; i++) {
var label = fieldVal[i].Label;
var guid = fieldVal[i].TermGuid;
//...
}
},
function(sender,args){
console.log(args.get_message());
});

AngularJS Array Not Loading On View Load, but Alerts/Console Work

I am trying to push values into an array as follows, but it is showing as an empty array. Alerting works. I am sure I am missing something obvious. Any clues? I have included the code with the just the array push attempt and another entry of code that has working alerts.
$scope.termsArray = [];
execOperation();
function execOperation() {
//Current Context
var context = SP.ClientContext.get_current();
//Current Taxonomy Session
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
//Term Stores
var termStores = taxSession.get_termStores();
//Name of the Term Store from which to get the Terms.
var termStore = termStores.getByName("Taxonomy_111111111111");
//GUID of Term Set from which to get the Terms.
var termSet = termStore.getTermSet("12345-55-689");
var terms = termSet.getAllTerms();
context.load(terms);
context.executeQueryAsync(function () {
var termEnumerator = terms.getEnumerator();
while (termEnumerator.moveNext()) {
var currentTerm = termEnumerator.get_current();
$scope.termsArray.push({
termName: currentTerm.get_name(),
termGUID: currentTerm.get_id(),
termSynonyms: 'Coming Soon'
});
}
}, function (sender, args) {
console.log(args.get_message());
});
}
Here is the code with working alerts:
function execOperation() {
//Current Context
var context = SP.ClientContext.get_current();
//Current Taxonomy Session
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
//Term Stores
var termStores = taxSession.get_termStores();
//Name of the Term Store from which to get the Terms.
var termStore = termStores.getByName("Taxonomy_111111111111");
//GUID of Term Set from which to get the Terms.
var termSet = termStore.getTermSet("12345-55-689");
var terms = termSet.getAllTerms();
context.load(terms);
context.executeQueryAsync(function () {
var termEnumerator = terms.getEnumerator();
var termList = "Terms: \n";
while (termEnumerator.moveNext()) {
var currentTerm = termEnumerator.get_current();
$scope.termsArray.push({
termName: currentTerm.get_name(),
termGUID: currentTerm.get_id(),
termSynonyms: 'Coming Soon'
});
termList += currentTerm.get_id() + currentTerm.get_name() + "\n";
}
alert(termList);
}, function (sender, args) {
console.log(args.get_message());
});
}
Here is the HTML output:
<div> {{termsArray}}</div>
It returns []
Update: If I click in an input box and back out, or click an alert and hit ok, it then loads the array instead of loading on page load.
I was able to track the issue down. It appears that Angular doesn't respect non-Angular functions on load, so I needed to wrap the $scoped array in a $scope.apply. Please see here for details: Execute SharePoint Function On Page Load in AngularJS Application ($scope issue???)

How to get SharePoint taxonomy terms programmatically using JSOM?

Sometimes there is a requirement to fetch the SharePoint taxonomy term sets programmatically. So, how to get SharePoint taxonomy terms programmatically using JSOM ?
Here is a way to fetch SharePoint taxonomy terms using JavaScript code:
$(document).ready(function () {
ExecuteOrDelayUntilScriptLoaded(function () {
SP.SOD.registerSod('sp.taxonomy.js', "/_layouts/15/sp.taxonomy.js");
SP.SOD.executeFunc('sp.taxonomy.js', false, Function.createDelegate(this, function () {
var context = SP.ClientContext.get_current();
var taxonomySession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
var termStore = taxonomySession.get_termStores().getByName("Taxonomy_qeFlDdEX32yZ3Q7EpEIeMQ==");
var termSet = termStore.getTermSet("ed6d3beb-6a49-4444-bc5d-456f747e139d");
var terms = termSet.getAllTerms();
context.load(terms);
context.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
var termsEnumerator = terms.getEnumerator();
var menuItems = new Array();
while (termsEnumerator.moveNext()) {
var currentTerm = termsEnumerator.get_current();
var targetGroups = document.getElementById("selectTaxonomy");
var taxoGroup = document.createElement("option");
taxoGroup.text = currentTerm.get_name();
targetGroups.add(taxoGroup);
}
}), Function.createDelegate(this, function (sender, args) {
alert('The error has occured: ' + args.get_message());
}));
}));
},"sp.js")
});

returning values from an async delegate function

I am working with the Sharepoint Client Object Model using javascript and looking to make as much of my code as reusable as possible.
Examples of using the COM usually looks like this with a call and then a success delegate function to output the results.
function loadProfile()
{
var context = SP.ClientContext.get_current();
var web = context.get_web();
var userInfoList = web.get_siteUserInfoList();
camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('');
this.listItems = userInfoList.getItems(camlQuery);
context.load(listItems);
context.executeQueryAsync(Function.createDelegate(this, this.onProfileSuccessMethod), Function.createDelegate(this, this.onFail));
}
function onProfileSuccessMethod(sender, args)
{
var item = listItems.itemAt(0);
var first_name = item.get_item('FirstName');
var last_name = item.get_item('LastName');
alert(first_name + " " + last_name);
}
function onFail(sender, args)
{
alert('Error: ' + args.get_message() + '\n' + args.get_stackTrace());
}
What I am trying to achieve is being able return the values after instantiating an object but given that it is asynchronous I am not sure how this is possible, would I need to "listen" for the call to complete before values are returned.
Would it be something like this? Or can you not have a delegate function internal to the function it creates it from. Apologies for my limited understanding!
var profile = new loadProfile("testid");
alert(profile.onProfileSuccessMethod());
function loadProfile (id)
{
this.user_id = id;
var context = SP.ClientContext.get_current();
var web = context.get_web();
var userInfoList = web.get_siteUserInfoList();
camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('');
this.listItems = userInfoList.getItems(camlQuery);
context.load(listItems);
context.executeQueryAsync(Function.createDelegate(this, this.onProfileSuccessMethod), Function.createDelegate(this, this.onFail));
this.onProfileSuccessMethod = function()
{
var item = listItems.itemAt(0);
this.first_name = item.get_item('FirstName');
this.last_name = item.get_item('LastName');
return this.first_name
};
}
If it is asynchronous, it is impossible to return values from it. You need to use a callback pattern.
function secondStep(data){
console.log(data)
}
var profile = new loadProfile("testid", secondStep);
and
function loadProfile (id, callback)
...
this.onProfileSuccessMethod = function(){
callback({});
}

Categories

Resources