Modifying the parent element's property when at least one child is selected: A simple guide

I am working with a tree structure made up of nodes called LayerNode. Each node has references to its children and parent.

My goal is to update the property of a parent node if any of its child nodes have the property selected = true.

  public recursiveSelectLayers(node: LayerNode) {
    if (node.children)
      node.children.forEach((childNode: LayerNode) => {
        childNode.parent = node;

        if (childNode?.parent?.selected)
          childNode.selected = childNode.parent.selected;

        if (childNode.selected && childNode.parent)
          childNode.parent.selected = childNode.selected;

        this.recursiveSelectLayers(childNode);
      });
  }

Additionally, if a parent node is marked as selected, all of its immediate children should also be set as selected.

The issue arises when one of the children is selected, causing the function mentioned above to select all descendants from that child to the root node.

Upon reflecting on the situation, I made a second attempt:

  public recursiveSelectLayers(node: LayerNode) {
    if (node.parent && node.selected) node.parent.selected = node.selected;

    if (node.children) {
      node.children.forEach((childNode: LayerNode) => {
        if (node?.selected) childNode.selected = node.selected;
        childNode.parent = node;
        this.recursiveSelectLayers(childNode);
      });
    }
  }

Scenario 1:

Parent 1 (selected)
   Child 1
   Child 2
   Child 3 (selected)

Scenario 2:

   Parent 1 (selected)
       Child 1 (selected)
       Child 2 (selected)
       Child 3 (selected)

Scenario 3:

   Parent 1 (selected)
       Child 1
       Child 2
       Child 3 (selected)
           Child 3.1 (selected)

Update:

  public recursiveSelectLayers(node: LayerNode) {
    if (node.id) this.flatlayers.set(node.id, node);
    if (node.children) {
      node.children.forEach(this.recursiveSelectLayers, this);
      node.selected =
        [...node.children].some((node) => node.selected) ||
        node?.parent?.selected;
    }
  }

Answer №1

I decided to give this a shot and run some tests on it. So far, it has passed 4 cases successfully.

function recursiveSelectLayers(node) {
  if (node.children) {
    node.children.forEach((childNode) => {

      if (node.parent && node.selected) {
        node.parent.selected = true;
      }

      recursiveSelectLayers(childNode);
    });
  }

  if (node.parent && node.parent.selected) {
    node.selected = true;
  }

  return node
}

// Testing different cases:

var case1 = {
  selected: true,
  children: [{}, {}, {
    selected: true
  }]
}
case1.children[0].parent = case1;
case1.children[1].parent = case1;
case1.children[2].parent = case1;

var case2 = {
  selected: true,
  children: [{
    selected: true
  }, {
    selected: true
  }, {
    selected: true
  }]
}
case2.children[0].parent = case2;
case2.children[1].parent = case2;
case2.children[2].parent = case2;

var case3 = {
  selected: true,
  children: [{}, {}, {
    selected: true,
    children: [{
      selected: true
    }]
  }]
}
case3.children[0].parent = case3;
case3.children[1].parent = case3;
case3.children[2].parent = case3;
case3.children[2].children[0].parent = case3.children[2];

var case4 = {
  children: [{}, {}, {
    selected: true,
    children: [{}]
  }]
}
case4.children[0].parent = case4;
case4.children[1].parent = case4;
case4.children[2].parent = case4;
case4.children[2].children[0].parent = case4.children[2];

console.log(recursiveSelectLayers(case1))
console.log(recursiveSelectLayers(case2))
console.log(recursiveSelectLayers(case3))
console.log(recursiveSelectLayers(case4))
<pre>
Case1:
   Parent 1 (selected)
      Child 1
      Child 2
      Child 3 (selected)

Case 2:
   Parent 1 (selected)
       Child 1 (selected)
       Child 2 (selected)
       Child 3 (selected)

Case 3:
   Parent 1 (selected)
       Child 1
       Child 2
       Child 3 (selected)
           Child 3.1 (selected)

Case 4:
   Parent 1
       Child 1 
       Child 2
       Child 3 (selected)
           Child 3.1 

</pre>

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

Using Redux to add an object to an array nested within another array

Hey there! I'm facing an issue with creating, updating, or deleting {note} in the [notes] array based on the operationId in the parent array id. I've tried using ADDNOTE but it's not working as expected. The problem is that without these fun ...

Send the canvas image dataURL for decoding and saving on the server using AJAX in conjunction with PHP

In the front-end, an image is generated (canvas.toDataURL) from the content of a div: ... var img = new Image(); var dataUrl; img.onload = function() { ...

Looking for guidance on sending data from a JS file to HTML using Nodejs? Seeking advice on various modules to achieve this task effectively? Let's

Looking for advice on the most effective method to transfer data from a JS file (retrieved from an sqlite db) to an HTML file in order to showcase it in a searchable table. My platform of choice is NodeJS. As a beginner, I am willing to put in extra time a ...

Using database entries to generate dynamic routes in express.js without the need for a server restart

I have created a custom Express instance for my KeystoneJS v5 app that serves data stored in a Postgres database with the following model: CREATE TABLE "Link" ( id integer DEFAULT PRIMARY KEY, customer text, slug text ); I've set up dyna ...

Tips for managing $rootScope in the provider's config function

Can someone help me understand how to work with $rootScope in a provider method? I'm unsure of how to properly inject it. that.app.config ['$authProvider', ($authProvider) -> $authProvider.configure apiUrl: '/api/v1&apos ...

In what way is the reference to "this" passed in the function that follows?

I came across the following example in the JS manual, which is functioning correctly: let worker = { someMethod() { return 1; }, slow(x) { alert("Called with " + x); return x * this.someMethod(); // (*) } }; function cachingDecorator ...

Thorough exploration of a collection of varied, categorized items

My goal is to have TypeScript ensure that all cases are covered when mapping over a union like this: type Union = { type: 'A', a: string } | { type: 'B', b: number } The handler for the Union: const handle = (u: Union): string = ...

How can I wait for an onclick action to pause, loop, or continue inside of a loop?

The form's onsubmit function triggers a pop-up message asking the user if they want to proceed before submitting the form. This requires the onsubmit function to wait for the user's final input in order to fully execute the form. Here is the cod ...

Manipulating Object origin data

I'm unsure if this can be achieved. I am aiming to create a header and footer that remain the same while only switching the content pages. The resources I have at my disposal cover HTML, JS, CSS, and JQuery. Below is a simplified version of my curre ...

I'm encountering a CastError while attempting to delete data in mongodb using Id

Encountered an issue while attempting to delete a MongoDB entry using the 'findByIdAndRemove' function in Mongoose. Specifically, it is throwing a 'Cast to ObjectId failed for value error'. Delete Service routes.delete('/:id' ...

Issue with dynamic code detected by Sys.Application.add_init

I am facing a challenge with an older application that I recently took over ownership of. My efforts to successfully run it have been partially fruitful, as I am encountering some strange behavior that seems to be related to Internet Explorer 11. Interesti ...

Finding the parent directory path within gulp.dest(): A step-by-step guide

I've recently started using Gulp and I'm facing an issue when trying to output my files to their parent directory. This is how my directories are structured: app/page_a/less/a.less app/page_a/css My desired outcome is: app/page_a/less/a.less ...

`How can I update a textbox's value using JQuery Ajax?`

Currently in the process of implementing an ajax call to update the value of a textbox: <div id="PNIncrementDiv" style="position:absolute; left: 730px; top: 15px; width: 350px;" class=""> <input id="TBIncrementTextBox" class="textbox" type="te ...

Trouble arises when attempting to create a two-column layout using Material UI's <Grid> component

My goal is to create a two-column layout where each column takes up half of the screen and has equal height. To better illustrate, take a look at this image. The code I've tried so far is not working as expected: import React from "react"; import { ...

API for Google Maps

Recently, I've been working on integrating Google Maps into my webpage. I successfully created a map that fills up 100% of the screen on its own HTML page. Now, I want to include a smaller version of the map within a div on my website. The include() f ...

The Firebase Function encountered an error: TypeError - it is unable to read the property 'replace' as it is undefined

I'm currently following Aaron Klasner's guide on Hackernoon for setting up a Medium feed in react. To test it locally, I need to find a way around the CORB that Medium uses to prevent local requests. I tried using a firebase function, but encou ...

An existing INPUT value can be modified by dynamically adding or subtracting values from SELECT OPTION

I currently have an <input readonly> field that displays the total_price value retrieved from a shopping cart stored in the database table. Moreover, I have included a <select> element with different transport options that can either increase o ...

Exploring the utilization of type (specifically typescript type) within the @ApiProperty type in Swagger

Currently, I am grappling with a dilemma. In my API documentation, I need to include a 'type' in an @ApiProperty for Swagger. Unfortunately, Swagger seems to be rejecting it and no matter how many websites I scour for solutions, I come up empty-h ...

The functionality of Protovis JavaScript is not supported within a dropdownlist's onchange event

I encountered an issue where one block of code works fine on its own, but when combined with another block, only one of them functions properly. The problem arises when I try to invoke a method from a dropdownlist using the onchange event, especially afte ...

Converting function arguments into key/value pairs: A simple guide

I am looking for a way to achieve the following in NodeJS: a = 10 b = 20 c = 30 d = 40 ...... ...... function createObject(a, b, c, d, ....) => { // This function is expected to return an object. // return { a : 10, b : 20 ...