Create custom html dropdown that gets SharePoint 2016 managed metadata values - javascript

I'm setting up a custom html form that uses javascript to add items into a SharePoint list. I need to get a list of terms from SharePoint 2016 managed metadata. Its a list of terms for office locations. I want to get these values and show them in a custom html drop down. Is this possible?

We can use the SharePoint web service to get the terms from managed metadata.
/_vti_bin/TaxonomyClientService.asmx
Or we can use JSOM in SharePoint to achieve it.
var termsList = "Terms: \n"
function showTerms(termSetId) {
//We need to load and populat the matching Term Set first.
var termSetEnum = termSets.getEnumerator();
while (termSetEnum.moveNext()) {
var currentTermSet = termSetEnum.get_current();
if (currentTermSet.get_id() == termSetId) {
//If termSet Matches, then get all terms.
context.load(currentTermSet);
context.executeQueryAsync(
function () {
//Load terms
var terms = currentTermSet.get_terms();
context.load(terms);
context.executeQueryAsync(
function () {
var termsEnum = terms.getEnumerator();
while (termsEnum.moveNext()) {
var currentTerm = termsEnum.get_current();
var termName = currentTerm.get_name();
var termId = currentTerm.get_id();
termsList += termName + ": " + termId;
//Check if term has child terms
if (currentTerm.get_termsCount() > 0) {
//Term has sub terms.
recursiveTerms(currentTerm, 1);
}
alert(termList);
}
},
function () {
//failure to load terms.
});
},
function () {
//failure to load current term set
});
break;
}
}
}
function recursiveTerms(currentTerm, nestedLoop) {
//Loop count for formatting purpose.
var loop = nestedLoop + 1;
//Get Term child terms
var terms = currentTerm.get_terms();
context.load(terms);
context.executeQueryAsync(
function () {
var termsEnum = terms.getEnumerator();
while (termsEnum.moveNext()) {
var newCurrentTerm = termsEnum.get_current();
var termName = newCurrentTerm.get_name();
termId = newCurrentTerm.get_id();
//Tab Out format.
for (var i = 0; i < loop; i++) {
termsList += "\t";
}
termsList += termName + ": " + termId;
//Check if term has child terms.
if (currentTerm.get_termsCount() > 0) {
//Term has sub terms.
recursiveTerms(newCurrentTerm, loop);
}
}
},
function () {
//failure to load terms
}
);
}
The following articles for your reference.
Using jQuery to return the Managed Metadata Term GUID
Accessing Taxonomy Term Store with JSOM

Related

For loop variable undefined in Javascript

I'm working on implementing a system where elements can be dragged and dropped to create flowcharts. My Issue is with saving the flowchart so that it could be reloaded when needed. For now I've created a method that saves all the previous data of the element onto the final array that holds only elements that are dropped on the container. But I'm getting a Trivial Error as Undefined variable on the debugging interface. Hence I'm not getting the intended output and the alert messages that I included are not being printed when the condition is met.
Code in Context
function saveFlowchart()
{
var nodes = [];
var matches = [];
var searchEles = document.getElementById("container").children;
for(var i = 0; i < searchEles.length; i++)
{
matches.push(searchEles[i]);
var idOfEl = searchEles[i].id;
if(searchEles[i].id !=null || searchEles[i].id !="")
{
var $element = $("#" + searchEles[i].id);
var dropElem = $("#" + searchEles[i].id).attr('class');
var position = $element.position();
position.bottom = position.top + $element.height();
position.right = position.left + $element.width();
alert("class:"+dropElem+"\nTop position: " + position.top + "\nLeft position: " + position.left + "\nBottom position: " + position.bottom + "\nRight position: " + position.right);
finalArray[idOfEl-1][0]= idOfEl;
finalArray[idOfEl-1][1]= dropElem;
var elId = parseInt(idOfEl);
if (dropElem == "stream ui-draggable")
{
for(var count=0;count<100;count++)
{
alert("One loop opened with count="+count);
if(createdImportStreamArray[count][0]==elId)
{
finalArray[elId-1][2]= createdImportStreamArray[count][1]; //Selected Stream from Predefined Streams
finalArray[elId-1][3]= createdImportStreamArray[count][2]; //asName
alert("createdImportStreamArray[count][0]==elId");
}
else if(createdExportStreamArray[count][0]==elId)
{
finalArray[elId-1][2]= createdExportStreamArray[count][1]; //Selected Stream from Predefined Streams
finalArray[elId-1][3]= createdExportStreamArray[count][2]; //asName
}
else if(createdDefinedStreamArray[count][0]==elId)
{
finalArray[elId-1][2]= createdDefinedStreamArray[count][1]; //Stream Name
finalArray[elId-1][3]= createdDefinedStreamArray[count][4]; //Number of Attributes
finalArray[elId-1][4]=[];
for(var f=0;f<createdDefinedStreamArray[r][4];f++)
{
finalArray[elId-1][4][f][0]=createdDefinedStreamArray[count][2][f][0]; //Attribute Name
finalArray[elId-1][4][f][1]=createdDefinedStreamArray[count][2][f][1]; // Attribute Type
}
}
alert("One loop closed with count="+count);
}
alert("Loop ended with count="+count);
}
else if (dropElem == "wstream ui-draggable")
{
ElementType="wstream";
}
// else if conditions...
alert(finalArray);
}
}
//Code to output the connection details in a json format
//The following is not affected by the above mentioned error
$(".node").each(function (idx, elem) {
var $elem = $(elem);
var endpoints = jsPlumb.getEndpoints($elem.attr('id'));
console.log('endpoints of '+$elem.attr('id'));
console.log(endpoints);
nodes.push({
blockId: $elem.attr('id'),
nodetype: $elem.attr('data-nodetype'),
positionX: parseInt($elem.css("left"), 10),
positionY: parseInt($elem.css("top"), 10)
});
});
var connections = [];
$.each(jsPlumb.getConnections(), function (idx, connection) {
connections.push({
connectionId: connection.id,
pageSourceId: connection.sourceId,
pageTargetId: connection.targetId
});
});
var flowChart = {};
flowChart.nodes = nodes;
flowChart.connections = connections;
flowChart.numberOfElements = numberOfElements;
var flowChartJson = JSON.stringify(flowChart);
//console.log(flowChartJson);
$('#jsonOutput').val(flowChartJson);
}
Debugging Interface
According to this the count variable in the for loop is undefined. I've tried taking the first statement var count=0 outside the loop declaration part and defining it in the very beginning of the method. But that simply checks for count=0 against the conditions and doesn't increment at all.
Any help in this regard will be highly appreciated as I've been working on this minor error for almost 2 days now.

ERROR: The collection has not been initialized

I am querying the contents of the Managed Metadata using the code below. I am encountering an error
The collection has not been initialized
when I am in the var level2TermsEnum = level2Terms.getEnumerator();
I have read that this is because of the deferred and promise of JavaScript and I can't seem to understand it. Maybe you could help me shed some light on here.
$(document).ready(function () {
var scriptbase = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/";
$.getScript(scriptbase + "SP.Runtime.js",
function () {
$.getScript(scriptbase + "SP.js", function () {
$.getScript(scriptbase + "SP.Taxonomy.js", function () {
context = SP.ClientContext.get_current();
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
//Term Stores
var termStores = taxSession.get_termStores();
//Term Store under which to create the group.
var termStore = termStores.getByName("Managed Metadata Service");
var termSet = termStore.getTermSet("7b6ee52v-3709-4181-a14d-b953f2ad0aad");
//Call your code here.
GetTermsFromTaxonomyStore();
});
});
});
var json = "";
function GetTermsFromTaxonomyStore() {
//Current Context
var context = SP.ClientContext.get_current();
//Current Taxonomy Session
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
var termStores = taxSession.get_termStores();
//Term Store under which to create the term.
//var termStore = taxSession.getDefaultSiteCollectionTermStore();
var termStore = termStores.getByName("Managed Metadata Service");
//Pass ID of the Meetings Term Set
var termSet = termStore.getTermSet("7b6ee52v-3709-4181-a14d-b953f2ad0aad");
var terms = termSet.get_terms();
context.load(terms);
context.executeQueryAsync(function () {
var level1Terms = terms.getEnumerator();
while (level1Terms.moveNext()) { //iterate thru Level1
var level1 = level1Terms.get_current();
if (level1.get_termsCount() > 0) { //check if Level1 has child
var level2Terms = level1.get_terms(); //get level2 terms of level 1 term
**var level2TermsEnum = level2Terms.getEnumerator();**
while (level2TermsEnum.moveNext())
{
var level2Term = level2TermsEnum.get_current();
var level2TermName = level2Term.get_name();
termsList += '"Level1":"' + level2Term.get_name() + '","Level2":"' + level2TermName + '"';
}
}
//console.log(currentTerm.get_name());
}
alert(termsList);
}, function (sender, args) {
console.log(args.get_message());
});
}
When the client object model returns a collection of objects for you, if each of those objects has its own sub-collections, they won't be initialized unless you explicitly ask for them to be loaded.
Similar to the answer provided here, you should be able to update your call to context.load() with an additional parameter telling it what to load.
I believe something like the below code will work, but I haven't tested it:
context.load(terms,"Include(Name,Terms,Terms.Include(Name))");

SharePoint 2013 list column title modification with javascript

I want to modify SharePoint 2013 list column title in views with javascript. There is a code I found here at stackoverflow, but I want to reference the column with the display name / internal name, not with the column position.
(function () {
function preTaskFormRenderer(renderCtx) {
modifyHeaderData(renderCtx);
}
function modifyHeaderData(renderCtx)
{
var viewTitle = renderCtx.viewTitle;
var linkTitleField = renderCtx.ListSchema.Field[1];
linkTitleField.DisplayName = viewTitle + ':' + linkTitleField.DisplayName;
}
function registerRenderer()
{
var ctxForm = {};
ctxForm.Templates = {};
ctxForm.OnPreRender = preTaskFormRenderer;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(ctxForm);
}
ExecuteOrDelayUntilScriptLoaded(registerRenderer, 'clienttemplates.js');
})();
Example:
SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPreRender: function(ctx) {
var field = getFieldByDisplayName(ctx,"Task Name");
if(field)
field.DisplayName = "Task Name:::";
}
});
});
function getFieldByDisplayName(ctx,name)
{
var result = ctx.ListSchema.Field.filter(function(f){return f.DisplayName == name;} ); //find field by display name
return result.length > 0 ? result[0] : null;
}
Result

Group By Query in Parse.com Cloud Code

I'm trying to get the results of the following sql command in Parse.com using cloud code.
Select shop, count(1) from Membership group by shop;
Is there a way to do so? or I can only get the number of members from selecting each shop?
var query = new Parse.Query("Membership");
query.equalTo("shop",shop_id);
var promise = query.find().then(function(results){
var number_of_membership_of_one_shop = results.leng
return results;
});
Parse unfortunately doesn't support group by.
You could first select all shops and then use a count query for each shop.
var query = new Parse.Query("Membership");
query.equalTo("shop",shop_id);
var promise = query.count().then(function(count){
var number_of_membership_of_one_shop = count;
return number_of_membership_of_one_shop;
});
If this is performing too many requests, you could select all the memberships and then count them on the client, but this will have a limit of 1000 so you may need to adopt some other techniques:
var query = new Parse.Query("Membership");
query.select("shop_id");
query.limit(1000);
var storeCounts = [];
queryObject.find({
success: function (results) {
for (var i = 0; i < results.length; i++) {
var shopId = results[i].get('shop_id');
if (!storeCounts[shopId]) {
storeCounts[shopId] = 0;
}
storeCounts[shopId]++;
}
},
error: function (error) {
alert("Error: " + error.code + " " + error.message);
}
});

Full url sharepoint item in Javascript

I'm trying to get the ContentTypeId of an item in sharepoint to get the full url of the item to get the binary of it and after send it to another plateform.
So here i put this code in element.xml to get the list ID and the document ids of the items i'm selecting, after this i send them to an ASPX page in a Sharepoint Dialog to define the destination of the items and after this in the postback, stream the binary and send it to the another platform. The problem is : To get the full url of my items i need ListId, ItemId and ContentTypeId.
Because i've found a code to stream the binary here :
How to Programatically Download files from sharepoint document library
And i need the full url of my items.
Any idea?
thanks
var iddocs ='';
var listId ='';
function geturl()
{
var context = SP.ClientContext.get_current();
this.web = context.get_web();
listId = SP.ListOperation.Selection.getSelectedList();
var list = this.web.get_lists().getById(listId);
var ok = false;
try
{
if ( SP.ListOperation.Selection.getSelectedItems(context) !== false)
{
var items = SP.ListOperation.Selection.getSelectedItems(context);
var url='listId:'+listId+ ' Number of selected items: ' + items.length ;
var i = 0;
if(items.length==0)
{
}else{
while( i != items.length )
{
url += ' Doc' + i + ': ' + items[i].id;
if(i>0){iddocs += '-'};
iddocs += items[i].id;
i++;
};
ok = true;
alert(url+' Id of clicked item:'+{ItemId});
};
};
}
catch(err)
{
};
return ok;
};
function OpenDialog(pidliste) {
var options = SP.UI.$create_DialogOptions();
options.width = 600;
options.height = 600;
options.title = 'Envoyer vers Nuxeo';
options.url ='/_Layouts/SPTest.CustomMenuItem/index.aspx?click={ItemId}';
if(pidliste){options.url += '&ids='+pidliste +'-'+ iddocs;};
options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);
SP.UI.ModalDialog.showModalDialog(options);
}
function CloseCallback(result, target) {
if (result == SP.UI.DialogResult.OK) {
}
if (result == SP.UI.DialogResult.cancel) {
SP.UI.Notify.addNotification('Opération canceled', false, '', null);
}
}
if(geturl())
{
OpenDialog(listId);
}else{
alert('Please select an item');
};
I've found the solution. In fact, items can be reached via :
{SiteUrl}+{ItemUrl}
The download function is linked in my first Post. But it doesn't work for multiple items, with this method you can only reach the properties of the item you're selecting.
You have to note that if you want to access to a SP file, you have to set your request.credential via :
request.Credentials = System.Net.CredentialCache.DefaultCredentials;
which will take the current credential you're using.
Hope it helps.

Categories