Skip to Content
Author's profile photo Libor Pisa

Customizing a Network Graph to Create an Org Chart

Network graph is a new control introduced in version 1.50 that allows you to display data as a network of nodes connected by lines. The nodes can be circular or rectangular and can be joined into groups. You can define custom attributes for nodes and groups of nodes as well as apply layout algorithms that define the graph’s appearance. Standard application of this controls looks like this:

 

 

Moreover, network graph is highly customizable and can be used in a variety of ways. I would like to show one of such customization variants for which this control was not primarily designed but can be used – Org Chart.

Imagine we have data with employees, their managers and colleagues, and we want to display this data as an organization hierarchy.

Let’s take a look at the key features of the network graph. With a network graph, you can:

  • Display tree-like org structure with all employees
  • For every employee, load employee’s manager
  • Easily search for all employees
  • Display members of the teams individually or as a single group
  • Apply color-coding to different teams or departments (not implemented in this example)

By the end of this tutorial, our org chart will look like this.

 

 

This example uses simulated dynamic loading (through JSON model) but you can just as well use it with OData service. In this example, each node can be collapsed and the root employee node has an upward arrow button that expands the tree one level up.

Let’s start with layout.

 

Layout algorithm

<layoutAlgorithm>
   <layout:LayeredLayout
         mergeEdges="true"
         nodePlacement="Simple"
         nodeSpacing="40"/>
</layoutAlgorithm>

 

Network graph supports several layout algorithms. In this example, we use the default “layered“ algorithm with some small adjustments.

  • mergeEdges: This flag merges all lines leading from node into single line. The graph looks more compact with this setting
  • nodePlacement: There are 3 ways to position nodes within a layered algorithm. “Simple” node placement attempts to place nodes as close to each other as possible to achieve a “tree-like” overall appearance.
  • nodespacing: We will set this option to 40 to make spaces between the nodes smaller. Because it looks better, the org chart appears lighter and more elegant

 

Node customization

By default, the graph supports two node shapes

  • Box (rectangular)
  • Circle (circular)

 

In our example, we will use the box shape, with a few adjustments. By default,  a box-shaped node has an icon, a title, and attributes arranged as shown in the image below.

 

On the other hand, we want to have a single employee picture with a name below it. We also need to use attributes to display the number of this employee’s direct reports. We need to leave the title empty and use the description to hold the employee’s name.

 

<image>
   <NodeImage src="{src}"
            width="80"
            height="100"/>
</image>

 

Important settings for the node:

<Node description="{title}"
     width="90"
     attributes="{attributes}"
     showActionLinksButton="false"
     showDetailButton="false"
     descriptionLineSize="0"
     shape="Box">

 

  • description: By default, a rectangular node displays an image and a title next to it (to the right). To modify this, we use an empty title and set the employee name as the description, which will be rendered below the image.
  • width: You must adjust the node’s width manually  to the image size. In our case, the image is  80px wide, while the node’s width is 90px.
  • attributes: Attributes display information about the team size. This option bind to its aggregation.
  • showActionLinksButton, showDetailButton: Hides the default action buttons (they are rendered after the user clicks the node), we will use custom buttons for all actions.
  • shape: Displays the node as a rectangle.

 

We need to bind the node to  more data from model that is not available in the properties. For such cases, we can use the customData binding.

 

<customData>
   <core:CustomData key="supervisor" value="{supervisor}"/>
   <core:CustomData key="team" value="{team}"/>
   <core:CustomData key="location" value="{location}"/>
</customData>

 

Using this data, we can show additional information about the employee, such as the team or location in the form of a popup.

 

Attributes are used to display team size.

<attributes>
   <ElementAttribute label="{label}" />
</attributes>

 

Line customization

With the lines, there is not much to customize in this example. We just hide the arrows by using the ‘arrowOrientation’ property.

 

<lines>
   <Line from="{from}" to="{to}" arrowOrientation="None" press="linePress" />
</lines>

 

To disable the default line popover we attach a ‘press’ event and set ‘bPreventDefault’.

 

GraphController.prototype.linePress = function (oEvent) {
   oEvent.bPreventDefault = true;
};

 

Dynamic data loading 

As mentioned before, we are trying to simulate an OData service. Even though our data is  stored in one JSON model, we manipulate it using filters the same way as you would do with OData service. To do so, we store an array of already loaded managers.

For every manager node, we create a special action button that triggers additional data loading. To achieve this, we attach an event handler to the “beforeLayouting” event where we manipulate all nodes. This event is triggered before the data is sent to the layout algorithm and rendered.

 

this._graph.attachEvent("beforeLayouting", function (oEvent) {

...

if (oNode.getKey() === this._sTopSupervisor) {
   sSupervisor = this._getCustomDataValue(oNode, "supervisor");
   if (sSupervisor) {
      oUpOneLevelButton = new ActionButton({
         title: "Up one level",
         icon: "sap-icon://arrow-top",
         press: function () {
            var aSuperVisors = oNode.getCustomData().filter(function (oData) {
                  return oData.getKey() === "supervisor";
               }),
               sSupervisor = aSuperVisors.length > 0 && aSuperVisors[0].getValue();

            this._loadMore(sSupervisor);
            this._sTopSupervisor = sSupervisor;
         }.bind(this)
      });
      oNode.addActionButton(oUpOneLevelButton);
   }
}

 

We add an “Up one level” button to the root manager node. Every manager has a “key” of his manager stored in the custom data, so we call “_loadMore” with this key.

 

Filtering

GraphController.prototype._setFilter = function () {
   var aNodesCond = [],
      aLinesCond = [];
   var fnAddBossCondition = function (sBoss) {
      aNodesCond.push(new sap.ui.model.Filter({
         path: 'id',
         operator: sap.ui.model.FilterOperator.EQ,
         value1: sBoss
      }));

      aNodesCond.push(new sap.ui.model.Filter({
         path: 'supervisor',
         operator: sap.ui.model.FilterOperator.EQ,
         value1: sBoss
      }));
   };

   var fnAddLineCondition = function (sLine) {
      aLinesCond.push(new sap.ui.model.Filter({
         path: "from",
         operator: sap.ui.model.FilterOperator.EQ,
         value1: sLine
      }));
   };

   this._mExplored.forEach(function (oItem) {
      fnAddBossCondition(oItem);
      fnAddLineCondition(oItem);
   });

   this._graph.getBinding("nodes").filter(new sap.ui.model.Filter({
      filters: aNodesCond,
      and: false
   }));

   this._graph.getBinding("lines").filter(new sap.ui.model.Filter({
      filters: aLinesCond,
      and: false
   }));
};

 

To simulate OData, we use filter objects. For each binding (nodes, lines), we create a filter representing the condition, such asid=’Boss1’, or manager =’Boss1’, or id=’Boss2’, or manager=’Boss2’, or a similar condition. The same applies to the lines. This narrows down the dataset and allows us to return only the managers and their teams that were already loaded.

 

Collapsing / expanding nodes

 

There are two ways to handle the expand/collapse behavior. Either the data is already loaded, so we simply hide the child nodes (this is the default network graph behavior), or the child nodes have to be loaded manually (as managers are not loaded with their team by default). In both cases, we need different buttons as shown in the code snippet below.

 

var sTeamSize = this._getCustomDataValue(oNode, "team");

if (!sTeamSize) {
   // employees without team - hide expand buttons
   oNode.setShowExpandButton(false);
} else {
   if (this._mExplored.indexOf(oNode.getKey()) === -1) {
      // managers with team but not yet expanded
      // we create custom expand button with dynamic loading
      oNode.setShowExpandButton(false);

      // this renders icon marking collapse status
      oNode.setCollapsed(true);
      oExpandButton = new ActionButton({
         title: "Expand",
         icon: "sap-icon://sys-add",
         press: function () {
            oNode.setCollapsed(false);
            this._loadMore(oNode.getKey());
         }.bind(this)
      });
      oNode.addActionButton(oExpandButton);
   } else {
      // manager with already loaded data - default expand button
      oNode.setShowExpandButton(true);
   }
}

 

As you can see, there are three cases we need to handle:

  • An employee without a team (the employee is not a manager) – we hide the expand/collapse button as there is nothing to expand.
  • A manager whose team has not been loaded yet – we create a new action button. In its press event, we call the already mentioneded “_loadMore” but with key of this node. This will load this manager’s team members.
  • A manager with already loaded team members – we show the default collapse/expand button and let the network graph run the show.

 

Custom popover

To display a custom popover, we must hide the default detail button, create a new one, and react to its press event. Again, we will use the ‘beforeLayouting’ event.

 

 

oDetailButton = new ActionButton({
   title: "Detail",
   icon: "sap-icon://person-placeholder",
   press: function (oEvent) {
      this._openDetail(oNode, oEvent.getParameter("buttonElement"));
   }.bind(this)
});

 

We create an XML fragment which contains ‘QuickView’ to display employee details. We only need to create a new JSON model and bind it to the fragment. We use custom data bound to every node from the model (as described in the before in the beginning of the article). For more information about ‘QuickView’ , see the API Reference.

 

GraphController.prototype._openDetail = function (oNode, oButton) {
   var sTeamSize = this._getCustomDataValue(oNode, "team");

   if (!this._oQuickView) {
      this._oQuickView = sap.ui.xmlfragment("sap.suite.ui.commons.sample.NetworkGraphOrgChart.TooltipFragment", this);
   }

   this._oQuickView.setModel(new JSONModel({
      icon: oNode.getImage() && oNode.getImage().getProperty("src"),
      title: oNode.getDescription(),
      description: this._getCustomDataValue(oNode, "position"),
      location: this._getCustomDataValue(oNode, "location"),
      showTeam: !!sTeamSize,
      teamSize: sTeamSize,
      email: this._getCustomDataValue(oNode, "email"),
      phone: this._getCustomDataValue(oNode, "phone")
   }));

   jQuery.sap.delayedCall(0, this, function () {
      this._oQuickView.openBy(oButton);
   });
};

 

Custom search

 

By default, search works  only with the data that the network graph has already loaded. Of course, when the data has to be loaded incrementally, this might be not sufficient, as the graph cannot display all data for the whole company (only maybe for a smaller company).

Fortunately, the Network Graph provides two events that allow us to fully customize how search works:

 

<Graph
…
searchSuggest="suggest"
search="search">
</Graph>

 

GraphController.prototype.suggest = function (oEvent) {
   var aSuggestionItems = [],
      aItems = this._oModel.getData().nodes,
      aFilteredItems = [],
      sTerm = oEvent.getParameter("term");

   sTerm = sTerm ? sTerm : "";

   aFilteredItems = aItems.filter(function (oItem) {
      var sTitle = oItem.title ? oItem.title : "";
      return sTitle.toLowerCase().indexOf(sTerm.toLowerCase()) !== -1;
   });

   aFilteredItems.sort(function (oItem1, oItem2) {
      var sTitle = oItem1.title ? oItem1.title : "";
      return sTitle.localeCompare(oItem2.title);
   }).forEach(function (oItem) {
      aSuggestionItems.push(new sap.m.SuggestionItem({
         key: oItem.id,
         text: oItem.title
      }));
   });

   this._graph.setSearchSuggestionItems(aSuggestionItems);
   oEvent.bPreventDefault = true;
};

 

The suggest function is called whenever a user wants to display data matching the filter condition. In this case, we  simply go through all data in the JSON model. . In such a case, one would have to create a custom function accepting search parameters.

 

The important part is, once you obtain the data you should call the ‘setSearchSuggestionItems’ method with an array of items to be displayed in the search field. Don’t forget to enable ‘preventDefault’, as calling OData service is asynchronous and we want to prevent default behavior until the data has been fully loaded.

 

GraphController.prototype.search = function (oEvent) {
   var sKey = oEvent.getParameter("key");

   if (sKey) {
      this._mExplored = [sKey];
      this._sTopSupervisor = sKey;
      this._graph.destroyAllElements();
      this._setFilter();

      oEvent.bPreventDefault = true;
   }
};

 

Search is triggered after the user selects an item from the suggested items. It resets all current items and display only the item that the user selected.

 

Additional customization and usage

There are several events provided by the Network Graph control that you can use for further customization. Moreover, most of the events support  ‘preventDefault’ , so you can prevent the default behavior, as shown in this table.

 

Object Event Result
Node press Action buttons won’t be shown.
Node collapseExpand Nodes won’t expand (collapse).
Node hover Hover class won’t be added.
Line press Dialog is not shown
Line hover Hover class won’t be added.
Group showDetail Detail dialog won’t be shown.

 

In this example, I’ve shown you how to customize network graph to edge cases it was not primary designed for. I hope you found this tutorial useful. If you have any questions or suggestions, please share them in the comments below. To explore other samples of network graph usage, see this link.

Assigned Tags

      39 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jose Erickson
      Jose Erickson

      Wonderful post. I just wanted to say that I had to do the same I  Webdynpro Abap in the past and now it is so easy with OData. Thanks for sharing.

      Author's profile photo Lokesh Jadhav
      Lokesh Jadhav

      Hi great post. I am new to this I wanted to know what is to be binded in the Graph>nodes and Node>attributes and attributes>ElementAttribute-label if the graph.json looks like below

      {
      	"graph": {
      		"graphName": "myGraph",
      		"nodes": [{
      			"id": "Oceanus",
      			"type": "titan",
      			"residence": "Othrys"
      		},{
      			"id": "Tethys",
      			"type": "titan",
      			"residence": "Othrys"
      		}],
      		"links": [{
      			"key": 1,
      			"source": "Oceanus",
      			"target": "Tethys",
      			"type": "marriedTo"
      		},{
      			"key": 2,
      			"source": "Tethys",
      			"target": "Oceanus",
      			"type": "marriedTo"
      		}]
      	}
      }

      I get the error missing template or factory function for aggregation attributes of Element

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      hello if you want to bind attributes i would suggest model structure like this one:

      {
        "nodes": [
          {
            "key": 3,
            "title": "Broth",
            "icon": "sap-icon://competitor",
            "shape": "Box",
            "status": "Success",
            "attributes": [
              {
                "label": "Energy",
                "value": "780 kcal"
              },
              {
                "label": "Protein",
                "value": "49 g"
              },
              {
                "label": "Carb",
                "value": "52 g"
              },
              {
                "label": "Fat",
                "value": "11 g"
              }
            ]
          }
       ], ....
      }
      

       

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      and XML binding:

      <Node
          key="{key}"
          attributes="{path:'attributes', templateShareable:true}">
            <attributes>
      	<ElementAttribute label="{label}" 
                                value="{value}"/>							
            </attributes>
      </Node>
      

       

      Author's profile photo Lokesh Jadhav
      Lokesh Jadhav

      Thank Libor that made some things clear.  I will make changes accordingly.

      Author's profile photo Loucas Stylianou
      Loucas Stylianou

      Hi Libor,

       

      Very nice post! Can you please give us more detail where do you place the following code ?

       

      <image>
         <NodeImage src="{src}"
                  width="80"
                  height="100"/>
      </image>

      I was not able to find NodeImage control in the graph library.

      Kind regards,

      Loucas Stylianou

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      Hello as we are continually trying to improve the graph, this feature was added in 1.52. I'm sorry I didn't mention it precisely. My bad. Sorry.

      Author's profile photo Loucas Stylianou
      Loucas Stylianou

      Thanks Libor!

       

      Can you please let us know when the 1.52 version will be available ?

       

      Kind regards,

      Loucas Stylianou

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      As far as i know, it's not officially announced. It should be somewhere around 31.1. 2018 but it may definitely change.

      Author's profile photo Loucas Stylianou
      Loucas Stylianou

      Thanks Libor!

      Author's profile photo Lokesh Jadhav
      Lokesh Jadhav

      Hi Libor,

      I encountered one more problem. I am not specifying any layouting algorithm. But still I get the following error

      Error in layouting algorithm. - SecurityError: Failed to construct 'Worker': Script at 'https://sapui5.hana.ondemand.com/resources/sap/ui/thirdparty/klay.js' cannot be accessed from origin 'https://webidetesting6****-d*****trial.dispatcher.hanatrial.ondemand.com'.

      Is this something similar to cross origin thing or is this because I haven't specified any layout algortihm?

       

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      Hello,

      for security reasons worker refuse to be created from other domain so you need to have sap-ui-core.js src on same domain as the app itself.

      We are working on a fix to disable worker for situations where this is for any reason not possible, but it's not deployed yet.

       

       

       

      Author's profile photo Marcus Hemmen
      Marcus Hemmen

      It won't run with LayeredLayout. It only works with ForceBasedLayout. I always get the following error Uncaught (in promise) undefined. Please help me. Thank you

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      hello, its probably the same issue, ive answered earlier:

      for security reasons worker refuse to be created from other domain so you need to have sap-ui-core.js src on same domain as the app itself.

      We are working on a fix to disable worker for situations where this is for any reason not possible, but it’s not deployed yet.

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      btw from version 1.54 this should be already fixed.

      Author's profile photo Former Member
      Former Member

      When will the version 1.54 will be available in the Cloud?

      Author's profile photo Axel Mohnen
      Axel Mohnen

      Hi Libor,

      thanks a lot for this nice blog. I did the same in the past by using a D3.js libary and it was a hell of work comparing to this.

      Do you know if drag-and-drop of nodes will be supported as well?

       

      Thanks,

      Axel

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      Hello,

      drag&drop, has the problems that we don't have separated algorithm for positioning lines. In future there are plans to introduce some our own layouting  algorithms for basic scenarios, in such case i guess drag&drop nodes could be relatively easy.

      Anyway I guess it will be several months minimum till we get there and I can't promise this will 100 % happen.

      Libor

       

      Author's profile photo Christoph Bühlmann
      Christoph Bühlmann

      Thank you for this great post. Could you give me a short idea of what the corresponding oData Service has to look like? What entities will I need to reflect the hierarchy. I did not really understand that part when looking at the sample in the sapui5 Demo Kit.

      Thank you
      Christophe

      Author's profile photo Ramamani M
      Ramamani M

      Hi Libor,

      I want to customize the Node event here:

      I want to show the action buttons on hover of the node. And was able to achieve this by attaching the hover event and a listener. But I also want to hide it when I do a mouse out. How to achieve mouse out on a node?

      Please help!!

      Thanks,

      Ramamani M

      Author's profile photo Christoph Bühlmann
      Christoph Bühlmann

      Dear Libor

      did you ever have a situation where you had to draw assistant positions in your OrgChart? How could this be achieved?

      An assistant position for us should be shown on a side line, below the position they assist, but above those who report to that same position.

      Thanks for some input.
      Christophe

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      Hello,

      not sure I understand correctly.

      By theory, you can try move your assistants nodes up a bit in the post processing routine (affterLayouting event) and call setX,setY.

       

      Of course lines have to be changed accordingly.

      Libor

      Author's profile photo Christoph Bühlmann
      Christoph Bühlmann

      Dear Libor

      thanks for the reply. I was trying to make my request work with moving up the respective nodes but this is not the final solution that I need. I would rather need the assistant positions on a separate row and with only straight lines to the side / without a kink.
      You can see two assistant positions in the picture below.

      Do you have an idea on how to realize this?

      Thanks and best regards
      Christophe

      Author's profile photo Italo Lombardi
      Italo Lombardi

      Dear Libor,

      I am trying to create an OrgChart, but I have too many nodes on the same level.

      Is it possible to put them in multiple rows? For example, dividing 20 nodes into 4 rows of 5?

      Or maybe can I limit the width of the graph content to force the rendering in multiple rows?

      Thanks for your help.

      Regards

      Italo

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      hello,

      this is unfortunately not possible. There is no way to force algorithm to limit rows or similar stuff.

      Width graph won't help either as the layout machine set the width for the graph not the opposite 🙂

      Libor

      Author's profile photo Italo Lombardi
      Italo Lombardi

      Hi,

      that is a really bad news for our project.

      Could I ask you if you have any other idea on how to solve our problem?
      Maybe using another structure different than the OrgChart?

      Thanks for your help Libor.

      Regards,
      Italo

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author
      September 6, 2018 at 9:40 am

      well the only way i can see (if you want to use this control) is writing your own layouting algorithm, which is a pain in general, but for tree (what org. chart by theory should be) it’s doable i guess.

       

      here is an example how to do that :

      https://sapui5.hana.ondemand.com/#/sample/sap.suite.ui.commons.sample.NetworkGraphAirports/preview

       

      the important is this line :

      oGraph.setLayoutAlgorithm(new NoopLayout());

       

      which basically turns off the default layouter. You have to create some suff for lines too.

      Author's profile photo Nicolas Hiege
      Nicolas Hiege

      Hello there,

      great blog to begin with.

      I have to use the Network-Graph to show some processes within our company.

      For this, I wanna use the standard Network-Graph. My data should come from an OData-Service.

      Am I right with my assumption that I need only two entities for this? One for the lines and one for the Nodes with a relationship?

      Regards,

      Nicolas

      Author's profile photo Italo Lombardi
      Italo Lombardi

      Hello Nicolas,

      yes, just two entities. I did something similar with OData and it works.

      Author's profile photo Italo Lombardi
      Italo Lombardi

      Dear Libor,

      I changed a few things in my OrgChart and now it seems working fine but I notice one issue that I do not like.

      Even in the example, nodes are not sorted properly by name, in fact, Doris is the last one in her row.  (https://sapui5.hana.ondemand.com/1.56.9/#/sample/sap.suite.ui.commons.sample.NetworkGraphOrgChart/preview)

      I am sure that my entries (nodes and lines) in the DB are adequately sorted and even the algorithm gets them in order but after the rendering, they are not sorted alphabetically.

      Is there a way to fix this problem?

      Thanks very much.

      Regards,

      Italo

       

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      Hello,

      I am afraid we are not able to change such stuff as the layouting algorithm is out of our hands. i don't see any way how to achieve this 🙁

      Author's profile photo Italo Lombardi
      Italo Lombardi

      Hi,

      I was trying to understand how nodes are sorted, but I don't see any logic.

      In fact, I did some tests (sorting my nodes before the layout, generate lines dynamically and much more) but I can't understand the algorithm.

      Do you know anything about that? I thought if we can't change the layouting algorithm, maybe we can "simulate" the sorting in a different way.

      Thanks for your answer Libor.

      Author's profile photo Libor Pisa
      Libor Pisa
      Blog Post Author

      Hello, as said layouter is 3rd party stuff so I can’t serve here ?

      Author's profile photo Fatih ERDEM
      Fatih ERDEM

      Hi Libor,

      I opened a question about network graph.  A question about this topic

      Can you write your opinion?

      Author's profile photo Nicolas Hiege
      Nicolas Hiege

      Hello there,

      I’ve got yet another question.

      I try to build a Tree in which there is an explicit order like:

      But there seems to be no order, in which the nodes are arranged within one level. So my try looks more like this:

      So is there a way to bring order to my tree? Without the use of the “x” and “y” coordinates?

      Thank you in advance

      Nicolas

      Author's profile photo Dhiraj Kumar Barnwal
      Dhiraj Kumar Barnwal

      Hi Libor Pisa,

       

      I am working on network graph to display  Org Structure and I am getting error for some of the data.

      If any Node having multiple supervisor that time getting error : Data not consistent.

      Below is the scenario :

      Suppose NODE : 5000123 report to 5000130 & 5000140 at the same time so 500023 having multiple supervisor and both supervisor are in different organization.

       

      Please could you suggest how to resolve the issue.

       

      Thanks & Regards,

      Dhiraj

      Author's profile photo Chris Mills
      Chris Mills

      Hi Libor,

      Thanks for the post, we were planning on using the NetworkGraph control to replace a 3rd party org chart solution, but one issue i'm having is doesn't seem like NetworkGraph supports exporting to an image (JPG/PNG) or PDF. Are you aware of any way? Or if this is on the planned roadmap for the NetworkGraph control (i'm on UI5 1.65)

      Looks good otherwise but this one is a show stopper for us. I've tried some other approaches (getting SVG and converting to canvas via canvg library and downloading this and also copying the HTML nodes in to a canvas using html2canvas library) but neither of these seem to work.

      Thanks

      Chris

      Author's profile photo AjeethKumar R
      AjeethKumar R

      Hey, Any Idea how can I Increase the Node Height of Box-type? Here I am not using any image in my solution. I just want to increase the Node Height whereas I am able to increase the Node Width only.

      Author's profile photo Sikander Hay
      Sikander Hay

      How to Print  Network ORG-Graph ?

      Kindly Help Out to Below Code.

      oToolbar.insertContent(new sap.m.Button("btn", {
      
      icon: "sap-icon://print",
      text: "PrintPDF",
      type: "Accept",
      
      press: function() {
       var ctrlString = "width= 800px, height=600px"; // control page size
      var wind = window.open("","Print",ctrlString);
      var sContent = this.byId("__shell0").exportToSVGString
      ({ // read content and fit with page size
      width: 800,
      height: 600
      }); 
      var sContent1 = document.getElementById("__xmlview0--graph").outerHTML; 
      // header area
      wind.document.write(sContent1 + sContent);
      wind.print();
      
      }
      }),0);