0

I'm currently trying to create a "Child Node" using Javascript by grabbing the users input and selection of their "Heading" where the Child node is going to go under.

function addNavigationNodesChild() {
    var idOfParentNode = $('#selectChildParentNavNode').val();
    var nameOfParentNode = $('#selectChildParentNavNode option:selected').text();
    var clientContextChild = new SP.ClientContext(siteRelURL);

    if (clientContextChild != undefined && clientContextChild != null) {
        var webChild = clientContextChild.get_web();

       var quickLaunchNodeCollectionGet = webChild.get_navigation().get_quickLaunch();
       var quickLaunchNodeCollectionGetData = quickLaunchNodeCollectionGet.get_item(idOfParentNode).get_children();


        for (var c = 0; c < navArrayChild.length; c++) {
            var navObjectChild = navArrayChild[c];
            var navTitleChild = navObjectChild.title;
            var navUrlChild = navObjectChild.url;
            var navIsExternalChild = navObjectChild.isExternal;

            // Set properties for a new navigation node.
            var nnciChild = new SP.NavigationNodeCreationInformation();
            nnciChild.set_title(navTitleChild);
            nnciChild.set_url(navUrlChild);
            nnciChild.set_isExternal(navIsExternalChild);

            // Create node as the last node in the collection.
            nnciChild.set_asLastNode(true);
            quickLaunchNodeCollectionGetData.add(nnciChild);
        }
        clientContextChild.load(quickLaunchNodeCollectionGetData);
        clientContextChild.executeQueryAsync(onQueryNavSucceededChild, onQueryNavFailedChild);
        console.log(quickLaunchNodeCollectionGetData);


    }
}

The error I'm getting with this is: Cannot Read Property "get_children" of undefined. Any help is greatly appreciated.

Reference: idOfParentNode is being pulled from a different script which actually works and pulls the correct id's of all the Headings. I've assigned the script that pulls these id's to populate a drop down that users can select from with values.

Example in my HTML: <option value="5">Five</option> Where 5 is the idOfParentNode - also my Header that I want a child node to go into.

EDIT: I have also tried this, with error.

    function addNavigationNodesChild() {
    var idOfParentNode = $('#selectChildParentNavNode').val();
    var nameOfParentNode = $('#selectChildParentNavNode option:selected').text();
    var clientContextChild = new SP.ClientContext(siteRelURL);

    if (clientContextChild != undefined && clientContextChild != null) {
        var webChild = clientContextChild.get_web();
        var quickLaunchNodeCollection = webChild.get_navigation().getNodeById(idOfParentNode);
        console.log(quickLaunchNodeCollection);

        for (var c = 0; c < navArrayChild.length; c++) {
            var navObjectChild = navArrayChild[c];
            var navTitleChild = navObjectChild.title;
            var navUrlChild = navObjectChild.url;
            var navIsExternalChild = navObjectChild.isExternal;

            // Set properties for a new navigation node.
            var nnciChild = new SP.NavigationNodeCreationInformation();
            nnciChild.set_title(navTitleChild);
            nnciChild.set_url(navUrlChild);
            nnciChild.set_isExternal(navIsExternalChild);

            // Create node as the last node in the collection.
            nnciChild.set_asLastNode(true);
            quickLaunchNodeCollection.get_children.add(nnciChild);
            quickLaunchNodeCollection.update();
        }
        clientContextChild.load(quickLaunchNodeCollection);
        clientContextChild.executeQueryAsync(onQueryNavSucceededChild, onQueryNavFailedChild);
        console.log(quickLaunchNodeCollection);
    }
}

Here, I'm using getNodeById method but I get an error stating webChild.get_navigation(...).getNodeById is not a function

2 Answers 2

1

Solved with this solution.

    function addNavigationNodesChild() {
    var idOfParentNode = $('#selectChildParentNavNode').val();
    var nameOfParentNode = $('#selectChildParentNavNode option:selected').text();
    var titleOfNavNodeChild = document.getElementById('addNav1Child').value;
var urlOfNavNodeChild = document.getElementById('addNav2Child').value;
    var clientContextChild = new SP.ClientContext(siteRelURL);

    if (clientContextChild != undefined && clientContextChild != null) {
        var webChild = clientContextChild.get_web();
        var quickLaunchNodeCollection = webChild.get_navigation().get_quickLaunch();
        clientContextChild.load(quickLaunchNodeCollection);
        clientContextChild.executeQueryAsync(function () {

        var e = quickLaunchNodeCollection.getEnumerator();
        var notFound = true;
            while (notFound && e.moveNext()) {
            var parentNode = e.get_current();
            if (parentNode.get_title() === nameOfParentNode) {
            var childrenNode = parentNode.get_children();
            notFound = false;
            console.log("found it ")
            var nnciChild = new SP.NavigationNodeCreationInformation();
            nnciChild.set_title(titleOfNavNodeChild);
            nnciChild.set_url(urlOfNavNodeChild);
            nnciChild.set_isExternal(true);

            // Create node as the last node in the collection.
            nnciChild.set_asLastNode(true);
            childrenNode.add(nnciChild);
            clientContextChild.executeQueryAsync(onQueryNavSucceededChild, onQueryNavFailedChild);
            }
        }
    });
  }
}
0
0

Here is a more modern example (change get_topNavigationBar for get_quickLaunch as needed) using typescript and async/await:

  async addNavigationNode(title, url, parentTitle, external = true) {
    // Helper fn to wrap JSOM call into awaitable promise
    const executeQuery = async (context: SP.ClientContext) =>
      new Promise((resolve, reject) => context.executeQueryAsync(resolve, reject));
    // Get ctx, web and top navigation items
    const ctx = new SP.ClientContext();
    const web = ctx.get_web();
    const nav = web.get_navigation().get_topNavigationBar();
    // Load and execute so we can iterate the collection
    ctx.load(nav);
    await executeQuery(ctx);

    // Create the new node
    const newNode = new SP.NavigationNodeCreationInformation();
    newNode.set_title(title);
    newNode.set_url(url);
    newNode.set_isExternal(external);
    newNode.set_asLastNode(true);
    // Figure out where to put it: under a parent if specified, otherwise just add to the collection
    let parentNode: SP.NavigationNode = null;
    if (parentTitle) {
      // Look for the parent. Iterate through the top-level items
      const e = nav.getEnumerator();
      while (e.moveNext()) {
        const node = e.get_current();
        // Found it, set the parent node and stop iterating
        if (node.get_title() === parentTitle) {
          parentNode = node;
          break;
        }
      }
      // Add the new node as a child of the parent we just found
      if (parentNode) {
        const children = parentNode.get_children();
        children.add(newNode);
        ctx.load(children);
      }
    } else {
      // No parent: add the new node as a child of the top-level collection
      nav.add(newNode);
    }
    // Execute again to perform the operation
    ctx.load(nav);
    return await executeQuery(ctx);
  }

I find it easier to just add using this function, then go into the site settings navigation area to re-order items.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.