Using D3 to access a nested select and sibling from the JSON property of an object

I am attempting to include a sibling before a series of div elements that have been generated using the .enter() method. Here is my current setup:

const data = [
    {
        "name": "foo",
        "hierarchies": [
            {
                "name": "Alpha",
                "children": [
                    {
                        "name": "A1"
                    },
                    {
                        "name": "A2"
                    },
                ],
                "property": {
                    "name":"Sub-Alpha"
                }
            },
            {
                "name": "Bravo",
                "children": [
                    {
                        "name": "B1"
                    },
                    {
                        "name": "B2"
                    },
                ],
                "property": {
                    "name":"Sub-Bravo"
                }
            }
        ]
    }
]

const system = d3.select('body').selectAll('div')
    .data(data)
        .enter().append('div').classed("system", true)

const hierarchy = system.selectAll('.system')
    .data(function(d) { console.log(d.hierarchies); return d.hierarchies })
        .enter().append('div').classed("hierarchy", true)

const children = hierarchy.selectAll('.hierarchy')
    .data(function(d, i) { return d.children })
        .enter().append('div').classed("child", true)
        .text(function(d, i) { return d.name })

The code above generates the following output:

<div class="system">
  <div class="hierarchy">
    <div class="child">A1</div>
    <div class="child">A2</div>
  </div>
  <div class="hierarchy">
    <div class="child">B1</div>
    <div class="child">B2</div>
  </div>
</div>

My goal now is to insert a sibling element next to the .child elements which will display the text retrieved from hierarchies.property.name. The desired final output should be:

<div class="system">
  <div class="hierarchy">
    <div class="property">Sub-Alpha</div>
    <div class="child">A1</div>
    <div class="child">A2</div>
  </div>
  <div class="hierarchy">
    <div class="property">Sub-Bravo</div>
    <div class="child">B1</div>
    <div class="child">B2</div>
  </div>
</div>

Answer №1

If you want to avoid inserting a sibling, you can continue using the regular selections with append:

const property = hierarchy.selectAll('.property')
  .data(function(d) {
    return [d.property]
  })
  .enter().append('div').classed("property", true)
  .text(function(d) {
    return d.name
  })

To maintain this structure, simply create that selection after const hierarchy and before const children. This will result in the following layout:

<div class="system">
    <div class="hierarchy">
        <div class="property">Sub-Alpha</div>
        <div class="child">A1</div>
        <div class="child">A2</div>
    </div>
    <div class="hierarchy">
        <div class="property">Sub-Bravo</div>
        <div class="child">B1</div>
        <div class="child">B2</div>
    </div>
</div>

You can view the demo below:

const data = [{
  "name": "foo",
  "hierarchies": [{
      "name": "Alpha",
      "children": [{
          "name": "A1"
        },
        {
          "name": "A2"
        },
      ],
      "property": {
        "name": "Sub-Alpha"
      }
    },
    {
      "name": "Bravo",
      "children": [{
          "name": "B1"
        },
        {
          "name": "B2"
        },
      ],
      "property": {
        "name": "Sub-Bravo"
      }
    }
  ]
}]

const system = d3.select('body').selectAll('div')
  .data(data)
  .enter().append('div').classed("system", true)

const hierarchy = system.selectAll('.system')
  .data(function(d) {
    return d.hierarchies
  })
  .enter().append('div').classed("hierarchy", true)

const property = hierarchy.selectAll('.property')
  .data(function(d) {
    return [d.property]
  })
  .enter().append('div').classed("property", true)
  .text(function(d) {
    return d.name
  })

const children = hierarchy.selectAll('.hierarchy')
  .data(function(d) {
    return d.children
  })
  .enter().append('div').classed("child", true)
  .text(function(d) {
    return d.name
  })
<script src="https://d3js.org/d3.v5.min.js"></script>

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

Tips for utilizing the intro.js npm package with Meteor version 1.4.1.1

I'm currently integrating intro.js into my meteor application. import { Template } from 'meteor/templating'; import { ReactiveVar } from 'meteor/reactive-var'; // import introJs from 'intro.js'; var introJs = require(&a ...

Guide on extracting unique key values from an array by utilizing a different key

I have an array containing the names of products along with their storage capacities. let products = [{name: "samsung A", storage: "128GB"}, {name: "samsung B", storage: "128GB"}, {name: "samsung C", storag ...

Updating an array within an object that is nested inside another array in MongoDB

I am faced with the task of modifying an array of objects within another array, and I am struggling to figure out how to achieve this. The position of the element in the array is stored in a variable rather than a string, which complicates things for me. I ...

I need to streamline my expanding and repetitive jQuery code

Although I am not an expert in jQuery, I am currently learning and implementing it to handle the display of images based on user interactions. While the existing jQuery code is functional, I realize that it may not be the most efficient approach for a di ...

Guide to dynamically generating Angular watchers within a loop

I'm looking to dynamically create angular watches on one or more model attributes. I attempted the following approach: var fields = ['foo', 'bar']; for (var i=0, n=fields.length; i<n; i++) { $scope.$watch('vm.model.&ap ...

Adding numerous objects to a Vuex store using mutations

I am currently working with the following store setup: import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) export default new Vuex.Store({ plugins: [createPersistedState()], state: { ...

Aligning HTML elements side by side

I am currently utilizing reactJS to create a form. Within this form, I am attempting to include a text field, a button for copying the text to the clipboard, and a hyperlink that redirects to a valid website. The issue I am facing is evident in the provid ...

Ways to discover the titles of every sub-directory

Suppose I have the absolute path of a directory. Is there a method in JavaScript (Node.js) to determine how many sub-directories it has, and retrieve the names of all its sub-directories? I searched online but didn't come across any solution. ...

Verifying the presence of a number in mongodb

registerRouter.route('/uidcheck') .post((req, res, next) => { Register.find({ aadhaar: Register.aadhaar }) .then((user) => { res.statusCode=200; res.setHeader('Content-type', 'application/json'); res.json ...

Struggling to access the height attribute from a CSS file

Hey there. I'm pretty confident that the solution to my query is quite simple. So, I have a .css file with this particular code snippet: div.site { text-align:center; border:2px solid #4b6c9e; padding:1px; margin-top:10px; font-size:medi ...

Tips for implementing fluid transitions between mouse X and Y coordinates using JavaScript

I recently developed a function that enables a DOM element to follow the mouse cursor. You can check out the code here. Currently, I am looking for suggestions on how to add a nice animation to this feature. Ideally, I want to incorporate a slight delay w ...

Ways to utilize the this.context.router in ReactJS

Below is the code I have written: import React from 'react'; import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table' import sampleSystems from '../sample-systems'; class SystemTable extends React.Component ...

Number input in JavaScript being disrupted by stray commas

On my webpage, there are elements that users can control. One of these is a text input field for numbers. When users enter digits like 9000, everything functions correctly. However, if they use comma notation such as 9,000, JavaScript doesn't recogniz ...

Is it possible to share a variable between different scopes in an Angular environment?

As I dive into building my first real Angular.js application, focused on assisting judges during courtroom hearings, I am encountering various challenges and learning how to overcome them. The application consists of views such as Calendar, Documents, and ...

What is the best way to run a function once all resources have been resolved?

Is there a way to delay the execution of a function until all my resources have resolved successfully? I want to parse through the log array only after all the $resources have resolved and then push a single success notification to the UI instead of multip ...

Ensure that the event listener remains on the final element in the list

I have a list that contains multiple elements, with the last one triggering an event when clicked. This event adds another element to the list dynamically, as shown in this fiddle: https://jsfiddle.net/45vyLdra/ My goal is to ensure that the click event ...

Having trouble initiating MongoDB on localhost with node.js

I'm new to the world of node.js and MongoDB. Trying to set up a simple project has been quite the adventure for me. After navigating to my project directory, I kick things off by typing node init, sticking with the default choices. Following that, I ...

Tips on choosing and showcasing information from jQuery date and time picker

I am struggling to show the selected data from a jQuery date and time picker and save it to a database using PHP with MySQL. I am not sure how to retrieve the information. Here is the jQuery code for the date and time picker along with a suggested jQuery f ...

Avoiding the "urls" format using the onBeforeRequest function

chrome.webRequest.onBeforeRequest.addListener(function(details) { if (localStorage.on == '1') { return {cancel:true}; } }, {urls: ["*://*.domain1.net/*","*://*.domain2.com/*","*://*.domain3.com/*"], types: ["script","xmlhttpreques ...

Can you explain the concept of themes in Material UI?

I am trying to wrap my head around the concept of themes and what they are meant to represent. I have gone through the documentation, but I still find it confusing. For instance, here is a snippet of code that I am referring to. I just want to understand ...