The nodes.attr() function is invalid within the D3 Force Layout Tick Fn

I'm currently experimenting with the D3 Force Layout, and I've hit a roadblock when it comes to adding elements and restarting the calculation.

Every time I try, I keep encountering this error:

Uncaught TypeError: network.nodes.attr is not a function

Below is the code snippet causing the issue:

var topoConfig = {
  width: 600,
  height: 600
};

var network = {
  nodes: [],
  links: []
}

var tickFn = () => {
  network.nodes
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; });
  network.links
    .attr("x1", function(d) { return d.source.x; })
    .attr("y1", function(d) { return d.source.y; })
    .attr("x2", function(d) { return d.target.x; })
    .attr("y2", function(d) { return d.target.y; });
};

var svg = d3.select("body")
  .append('svg')
  .style('width', topoConfig.width + 'px')
  .style('height', topoConfig.height + 'px');

var force = d3.layout.force()
  .nodes(network.nodes)
  .links(network.links)
  .charge(-400)
  .linkDistance(80)
  .size([topoConfig.width, topoConfig.height])
  .on('tick', tickFn);

function reload(){
  var nodes = svg.selectAll('.node')
   .data(network.nodes, d => d.id);

  nodes.enter()
   .append('rect')
   .attr({
      width: 10,
      height: 10,
      x: function(d){return d.x},
      y: function(d){return d.y}
   });

   force.start();
}

function addNode(node){
  network.nodes.push(node);
  reload();
}

window.setTimeout(function(){
  addNode({
    "id": "fabric:a",
    "label": "Fabric Switch",
    "type": "fabric-switch",
    "x": 100,
    "y": 100
  });
}, 500)

If you want to check out the live example on JsFiddle, here's the link: https://jsfiddle.net/teone/wo2gv3ge/3/

Any suggestions on what could be going wrong in my implementation?

Thank you!

Answer №1

As previously mentioned by Lars in the comment, the attr method is accessible within d3 selections rather than JavaScript arrays.

Therefore, you must modify your tick function in the following manner:

var tickFn = () => {
  svg.selectAll('.node') //Where node represents the class name of node elements.
    .attr("x", function(d) { return d.x; })
    .attr("y", function(d) { return d.y; });
  svg.selectAll('.link') //Where link denotes the class name of link elements.
    .attr("x1", function(d) { return d.source.x; })
    .attr("y1", function(d) { return d.source.y; })
    .attr("x2", function(d) { return d.target.x; })
    .attr("y2", function(d) { return d.target.y; });
};

Please Note: If you are using rect to represent nodes, ensure that you update the attributes for x and y instead of cx and cy. (Utilize cx and cy attributes if the nodes are circle elements)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Strange behavior of Lambda function in Typescript

Within a larger class, I'm working with the following code snippet: array.map(seq => this.mFunction(seq)); After compiling using the tsc command, it becomes: array.map(function (seq) { return _this.mFunction(seq); }); Everything seems fine so f ...

Connect tinyMCE to knockout.js

Learn how to utilize tinyMCE custom binding using. public sealed class CabinetShapeEditModel { public string Description { get; set; } } When implementing in the view: <script type="text/javascript"> var jso = @Html.Raw(Json.Encode ...

The WebSocket connection in the browser, when accessed through a remote server, typically shows a CLOSED state in the readyState property during the on

Local server operations are running smoothly. However, when testing on a remote server with Nginx, the issue arises where the readyState inside the event handler onopen is consistently showing as CLOSED. Nginx configuration: server { server_name doma ...

What is the best approach to implementing a filter in Vue 2 that is also compatible with Vue 3?

Currently, I am utilizing Vue.js 2+ version and have implemented a date formatting filter to meet my needs. However, I recently found out that Vue 3 has removed the filter functionality in favor of using computed properties or methods. My dilemma now is ho ...

Upload an array of choices to the server by utilizing ng-model

I have almost resolved my issue, but now I need help with sending the data to the server. In my current situation, there is a form that includes employee details and projects for that employee (which can be multiple). When the user wants to add projects, ...

What is the correct way to use Deviceready in an Ionic application?

I am currently working on a mobile application built with Cordova and Ionic. The default page of the application requires the use of the SQLLite plugin. https://github.com/brodysoft/Cordova-SQLitePlugin The issue I am facing is that the view contains n ...

Increase the date and time by a specified number of days

After searching for solutions on how to add a specific number of days to a given date, I came across various methods. However, my requirement is to add days to both Date and Time in the format MM-DD-YYYY HH:MM:SS. I attempted a method which worked fine wh ...

Passing an array of objects as properties in React components

My functional component looks like this: function ItemList({ items }: ItemProps[]) { return <p>items[0].name</p> } Here is how I'm creating it: <ItemList items={items} /> The array items contains objects in the format [{name: &ap ...

Rearrange element's placement using Jquery Drag & Drop

I am experiencing difficulties in positioning my elements after a drop event. Within my "list" of divs... In order to keep the divs together and update the list, I utilize jQuery's append function to move the element from the list to its designated ...

I encountered an issue with loading an array from session storage in Java Script

I am struggling to restore and reuse a created array in HTML. I attempted using JSON, but it was not successful for me. In the code below, I am attempting to reload items that were previously stored in an array on another page. However, when I try to loa ...

Attempting to output properties from an Express/Mongo API by utilizing a React.js frontend

I am currently in the process of developing a simplistic fictional sneaker application with the MERN stack. While I wouldn't classify myself as a beginner, I'm also not an expert. I successfully created the backend and generated a json rest-api. ...

Encountering a blank page and error message on Vue JS while attempting to generate a JSON file within the

Recently, I encountered a peculiar problem while working on my Vue project using Vue UI in Visual Studio. Before connecting my API, I wanted to prototype and experiment with fake data. So, I decided to create a JSON file in the assets folder to store my m ...

Change a JavaScript object into an array with different options while still maintaining the keys

I am attempting to transform the following JavaScript object: image_uploads: [ 0: { upload_id: 50, }, 1: { upload_id: 51, }, 2: { upload_id: 52, }, ] Into separate entries using this structure for inclusion in the body of a POST r ...

Encountering difficulty when determining the total cost in the shopping cart

I am currently working on a basic shopping cart application and I am facing an issue when users add multiple quantities of the same product. The total is not being calculated correctly. Here is my current logic: Data structure for Products, product = { ...

Is it possible for me to transform this code into a useful helper function?

I am looking to optimize this conditional code by converting it into a helper function using a switch statement instead of multiple if statements. How can I achieve this in a separate file and then import it back into my component seamlessly? import { ...

Issue with Braintree Integration - custom form failing to generate nonce

When I followed the code in the documentation, the nonce did not appear at the server side and I couldn't find any hidden input field for the nonce being submitted. I was only able to make it work with the drop-in form and could see the nonce on the ...

how to open a new tab using JavaScript with Selenium

My code is supposed to open a new window that goes from the login window to the main menu, module, reports, and finally the report name. The report name should be opened in the next tab. Issue: The report name is not opening in a new tab; it's openin ...

The functionality of document.elementFromPoint(x, y) seems to be faulty in accurately identifying child elements

I've been trying to retrieve the element over which a "drop" event occurs, but I keep getting unexpected results. It consistently returns parent elements instead of the actual child element where the dragged element is dropped on. For a full code exa ...

Issue: The module '[object Object]' could not be located

const express = require('express'); const app = express(); const jade = require('jade'); const path = require('path'); const server = require('http').createServer(app); const io = require('socket.io').liste ...

Performing an automated check on user messages every 60 seconds using JQuery and Ajax

I am in the process of developing a website with notification features, and I am looking to implement a script that will check for new messages every 60 seconds. The goal is to pass the user id through the script to trigger an alert (currently using a ba ...