Error - Unhandled promise rejection while using Neovis.js

Hi,

Is there any way to hit a Neovis twice or more than once in a program. Because i use Neovis.js code in two of my angular functions -

EwayBill() and Collection(). Both have Neovis.js code but different cypher queries. On page load , i want both the respective outputs of EwayBill and Collection Nodes. But that doesn't happen and i get the output -


Unhandled promise rejection TypeError: Cannot read property 'hasChildNodes' of null
    at t.value (neovis.js:35248)
    at new n (neovis.js:35243)
    at Object.onCompleted (neovis.js:36674)
    at eval (neovis.js:34269)
    at run (neovis.js:11126)
    at eval (neovis.js:11139)
    at MutationObserver.flush (neovis.js:10385)
    at ZoneDelegate.invoke (zone.js:388)
    at Object.onInvoke (core.js:4062)
    at ZoneDelegate.invoke (zone.js:387)
(anonymous) @ neovis.js:11156
perform @ neovis.js:11098
(anonymous) @ neovis.js:11150
run @ neovis.js:35611
runIfPresent @ neovis.js:35640
onGlobalMessage @ neovis.js:35680
ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:4053
ZoneDelegate.invokeTask @ zone.js:420
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
postMessage (async)
registerImmediate @ neovis.js:35691
setImmediate @ neovis.js:35598
onUnhandled @ neovis.js:11146
(anonymous) @ neovis.js:11142
flush @ neovis.js:10385
ZoneDelegate.invoke @ zone.js:388
onInvoke @ core.js:4062
ZoneDelegate.invoke @ zone.js:387
Zone.runGuarded @ zone.js:151
(anonymous) @ zone.js:129
characterData (async)
notify @ neovis.js:10406
(anonymous) @ neovis.js:10432
notify @ neovis.js:11107
then @ neovis.js:11253
_releaseConnection @ neovis.js:30699
releaseConnection @ neovis.js:30666
onCompletedWrapper @ neovis.js:34268
onCompleted @ neovis.js:33050
onCompleted @ neovis.js:34765
_handleMessage @ neovis.js:31459
Connection._dechunker.onmessage @ neovis.js:31404
_onHeader @ neovis.js:30549
AWAITING_CHUNK @ neovis.js:30502
write @ neovis.js:30560
self._ch.onmessage @ neovis.js:31377
WebSocketChannel._ws.onmessage @ neovis.js:30217
wrapFn @ zone.js:1188
ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:4053
ZoneDelegate.invokeTask @ zone.js:420
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:496
    invokeTask @ zone.js:1540
   globalZoneAwareCallback @ zone.js:1566

Now to avoid the above error i tried to change the code for HTML page in EwayBill() and Collection(). I changed a little code and defined EwayBill output as -

    this.vizEwayBill = new NeoVis.default(config);
    this.vizEwayBill.render();
    console.log(this.vizEwayBill);

And to Collection output as -

       this.vizCollection = new NeoVis.default(config);
      this.vizCollection.render();
      console.log(this.vizCollection);

Instead of this -

     this.viz = new NeoVis.default(config);
     this.viz.render();
     console.log(this.viz);

But i still get error -


Unhandled promise rejection TypeError: Cannot read property 'hasChildNodes' of null
    at t.value (neovis.js:35248)
    at new n (neovis.js:35243)
    at Object.onCompleted (neovis.js:36674)
    at eval (neovis.js:34269)
    at run (neovis.js:11126)
    at eval (neovis.js:11139)
    at MutationObserver.flush (neovis.js:10385)
    at ZoneDelegate.invoke (zone.js:388)
    at Object.onInvoke (core.js:4062)
    at ZoneDelegate.invoke (zone.js:387)
(anonymous) @ neovis.js:11156
perform @ neovis.js:11098
(anonymous) @ neovis.js:11150
run @ neovis.js:35611
runIfPresent @ neovis.js:35640
onGlobalMessage @ neovis.js:35680
ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:4053
ZoneDelegate.invokeTask @ zone.js:420
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
postMessage (async)
registerImmediate @ neovis.js:35691
setImmediate @ neovis.js:35598
onUnhandled @ neovis.js:11146
(anonymous) @ neovis.js:11142
flush @ neovis.js:10385
ZoneDelegate.invoke @ zone.js:388
onInvoke @ core.js:4062
ZoneDelegate.invoke @ zone.js:387
Zone.runGuarded @ zone.js:151
(anonymous) @ zone.js:129
characterData (async)
notify @ neovis.js:10406
(anonymous) @ neovis.js:10432
notify @ neovis.js:11107
then @ neovis.js:11253
_releaseConnection @ neovis.js:30699
releaseConnection @ neovis.js:30666
onCompletedWrapper @ neovis.js:34268
onCompleted @ neovis.js:33050
onCompleted @ neovis.js:34765
_handleMessage @ neovis.js:31459
Connection._dechunker.onmessage @ neovis.js:31404
_onHeader @ neovis.js:30549
AWAITING_CHUNK @ neovis.js:30502
write @ neovis.js:30560
self._ch.onmessage @ neovis.js:31377
WebSocketChannel._ws.onmessage @ neovis.js:30217
wrapFn @ zone.js:1188
ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:4053
ZoneDelegate.invokeTask @ zone.js:420
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:496
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566

Note : Only when i use this declaration that i get the output-

     this.viz = new NeoVis.default(config);
     this.viz.render();
     console.log(this.viz);

When i searched for "viz" in neovis.js code, i don't get any result.

Please help. I want more that one output in my html page at once.

1 Like

What is the value of config.container_id for each instance of Neovis? Are they the same? That error sounds like it's not able to find the container element for the visualization.

1 Like

Thanks William . Its resolved

1 Like

Hi Sucheta,
I am also facing the same issue. Can you share the resolution of this problem.

Error:
Unhandled promise rejection TypeError: Cannot read property 'hasChildNodes' of null
at t.value (neovis.js:35235)
at new n (neovis.js:35230)
at Object.onCompleted (neovis.js:36653)
at neovis.js:34256
at run (neovis.js:11113)
at neovis.js:11126
at MutationObserver.flush (neovis.js:10372)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runGuarded (zone.js:161)
at MutationObserver. (zone.js:144)

Thanks
Payal

Hi Payal,

Either the neovis.js plugin container_id as mentioned below in the configuration is notcorrectly mentioned. Or i even got it at times when it .i.e. the function was unable to find this instance of Neovis . It happens when the page loads and the html DOM i.e. your

hits before the config and query inside it (.i.e. the function) is called. Check the possibility of this.

var url = config1.neo4j_url;
var user = config1.neo4j_user;
var password = config1.neo4j_password;
var container_id = config1.container_id;

    var config = {
        **container_id: container_id,**
        server_url: url,
        server_user: user,
        server_password: password,
        labels: {
         

            "Organization": {
                "thickness": "weight",
                "caption": "value",
                "size": "pagerank",
                "community": "community",
               
            },
            "Parameter": {
                "thickness": "weight",
                "caption": "value",
                "size": "pagerank",
                "community": "community",
          }

}

Hi Sucheta,
I mentioned the correct container id. Kindly check the below code.

function draw(str){
    var viz;
        var config = {
            container_id: "display",
            server_url: "bolt://172.21.193.217:7687",
            labels: {
                 "Person": {
                    "caption": "name",
                    "size": "pagerank",
                    "community": "community",

                } 
            },
            relationships: {
                "INTERACTS": {
                    "thickness": "weight",
                    "caption": false
                }
            },
            /* initial_cypher: "{}{}{}".format("MATCH p=()-[r:HAPPENED_IN]->() RETURN p LIMIT 25") */
             /*initial_cypher: "MATCH p=()-[r:HAPPENED_IN]->() RETURN p"  */      
            initial_cypher:str
        };
    
        this.viz = new NeoVis.default(config);
        this.viz.render();
}

kindly share the color coding for specific nodes

Thanks
Payal

@sucheta @lyonwj

Hi Sucheta and William,

I'm getting the error related to the DOM. Basically, Cannot read property 'hasChildNodes' of null, DOM is trying to get rendered before the query finishes loading the required data. I'm using react based components. I checked my container_id and it works. I'm able to see the data on the console because as it an object and it gets updated. But when rendering I'm getting this error. Please let me know how to resolve this type of error. I'm attaching a picture of console as well for reference.

this.viz = new NeoVis.default(config);
this.viz.render();

Thanks,
Sharath

Hi Sharath,

You got it right , the DOM gets rendered before its functionthat has the query executes, that is why you get hasChildNodes of null error.

The solutions that occured to me are -
[1] I used an *ngIf ...in the html part of my angular framework. *ngIf is a directive that makes the DOM div execute only if it is true. Check out my code for reference.


<table *ngIf="afterExtract">
  <tbody>

    <br>
    <tr>
      <td>

        <div>

          <!-- Display Singular Graph & Display Neo4j Output-->
          <div *ngFor="let i of selectedAPINameLength">

            <p id="menuframe" style="font-size: 16px">{{i.nameSingular}} </p>

            <div id="vizSingular{{i.value}}"></div>
            <br>
          </div>

        </div>

      </td>
    </tr>
  
  </tbody>
</table>

In the above code - *ngIf = "afterExtract" is my condition that i put true only in the function where i write my config. To elaborate... i use *ngFor to execute multiple screens of neo4j output. And vizSingular{{i.value}} is my renderer.

You may refer this link of react to convert *ngIf of angular to react -

[2] Place the function such that it gets executed on click or just when the DOM uploads...for which i guess a little R&D is required .

Regards,
Sucheta

Hi Payal,

I did not see your post for a long time. Probably you have found out the solution by now. If not, please check the reply to Sharath in the below mail trail.

For the color - There are 5-7 basic colors for the nodes that paint the nodes. And when i rendered the neovis.js counterpart of Neo4j , i got plain grey colored nodes. SO i researched and got this query to run -


// -----------------  Color Cluster Query  ----------------------

CALL algo.labelPropagation(null,null,'OUTGOING',{write:true, partitionProperty:'partition', weightProperty:'count'})

[2] Also mention the key-value pairs of labels and relationships like -


  var config = {
      container_id: vizIdSingular,
      server_url: this.url,
      server_user: this.user,
      server_password: this.password,
      labels: {
   
        "Organization": {
          "thickness": "weight",
          "caption": "value",
          "size": "pagerank",
          "community": "community",
          "sizeCypher": "MATCH (n) WHERE id(n) = {id} MATCH (n)-[r]-() RETURN sum(r.weight) AS c"
        },
        "Parameter": {
          "thickness": "weight",
          "caption": "value",
          "size": "pagerank",
          "community": "community",
          "sizeCypher": "MATCH (n) WHERE id(n) = {id} MATCH (n)-[r]-() RETURN sum(r.weight) AS c"
        },
        "Department": {
          "thickness": "weight",
          "caption": "value",
          "size": "pagerank",
          "community": "community",
          "sizeCypher": "MATCH (n) WHERE id(n) = {id} MATCH (n)-[r]-() RETURN sum(r.weight) AS c"
        },

     
      
        "API": {
          "thickness": "weight",
          "caption": "value",
          "size": "pagerank",
          "community": "community",

        },

        "System": {
          "thickness": "weight",
          "caption": "value",
          "size": "pagerank",
          "community": "community",
        },
     
        "Method": {
          "thickness": "weight",
          "caption": "value",
          "size": "pagerank",
          "community": "community",
        },

      },
      relationships: {
        "Parameter": {
          "thickness": "weight",
          "caption": true,
          "community": "community",
          "color": 'red'
        },
        "Method": {
          "thickness": "weight",
          "caption": true,
          "community": "community",

        },
       
        "Port": {
          "thickness": "weight",
          "caption": true,
          "community": "partition",

        },
  
        "API": {
          "thickness": "weight",
          "caption": true,
          "community": "community",

        },
              },

      cluster_labels: {
        "Parameter": "partition"
      },

      initial_cypher: cypherQuery,
      arrows: true,
      hierarchical_layout: true,
      hierarchical_sort_method: "directed",

    };
    this.containerIdSingular = new NeoVis.default(config);
    this.containerIdSingular.render();
    this.loading = false;
    console.log(containerIdSingular);
  }

[3]
For a particular node -

Color Property
----------------

CALL algo.labelPropagation('NGOConnectionService','Parameter','OUTGOING',{write:true, partitionProperty:'community', weightProperty:'count'})

where - NGOConnectionService -> node
and
'Parameter' - > Relationship.

[4] Neo4j query reference -

[5] You can change the color of the nodes in Neo4j app by including the .grass file. Check out this post -

Regards,
Sucheta

@sucheta

Hi Sucheta,

Thanks for the idea. I think I did what you have mentioned. I declared one variable on my state and after the render, I'm updating the state with the data. Now I'm stuck because I'm not quite sure about how the rendering of graph of works like a visualization, which functions need to be triggered etc.

Below is the code for reference:

I'm able to see the data in this.viz only if I call the this.viz.render(). Is there any other way that we can get the data without calling this.viz.render()?

this.viz = new NeoVis.default(config);
this.setState({
      myObj: this.viz
});
this.viz.render();

I think the render() will execute the data loading part. But if it does, is there any way that we can use a callback function? Please let me know.

Thanks,
Sharath

Hi Sharath,

Let me tell you a scenario - what happened was there were more than 5,000 nodes and the DOM was taking a lot of time to load. So we thought of implementing a loader / a spinner to cover that loading time. We placed the loader at the start of the function and ended it after the this.viz.render(); (also tried just before the render();). However, to our surprise, we found out that the loader never worked. Because the render function is i guess works asynchronously. So the code doesn't execute in ascending order .ie. line by line i guess.
So i am not sure, where your setState would work.

why don't you try something like this -

render() {
  return (
this.props.showMe ? <table >
     <div id="viz"></div> 
</table>
  );
}

function neovis(){

this.showme.props=true;

var config = {....}


this.viz = new NeoVis.default(config);
this.setState({
      myObj: this.viz
});
this.viz.render();

}

I just tried out react now from web.. i don't know it really.

P.S.:


 return (

   this.props.showMe ?  <div id="viz"></div> 

  );

will not work. Atleast it did not work in my case anytime. It throws error. That is why i surrounded it in a table tag.

Hello,
I don't get why I still have the error. I am using a button to execute the function. Thank you in advance!

import React, { Component } from "react";
import NeoVis from 'neovis.js';
import Button from "components/CustomButton/CustomButton.jsx";

export default class Metiers2 extends React.Component {
  constructor(props) {
    super(props);
  }

  draw(){
    var config = {
      container_id : "viz",
      server_url: "bolt://localhost:7687",
      server_user: "neo4j",
      server_password: "neo4j",
      labels: {
      },
      relationships:  {
    
      },
    
    
    initial_cypher: "MATCH (n)-[r]->(m) RETURN n,r,m"
    };
    
    const viz = new NeoVis(config);
    viz.render();
    console.log(viz);
  }
 
  
  
}
render(){
  return(
    <div className="content">
    <Button
                bsStyle="info"
                pullRight
                fill
                type="submit"
                onClick={() => {
                  this.draw();
                }}
              >
                Afficher
    </Button>
    </div>
  );
}
}