1

I'm trying to create a tree. But I dont know how replace a item recursively inside a tree.

I have an array of items, each item if is on top parentId is undefined and if has clindren, each children has a parentId property that show how is his parent.

I'm trying to create a method that find that item inside children property, who can have 1 or more levels.

And if its possible return updated array

This is my code:

const onChangeStatusEditable = () => {
    const updatedBranch: IBranch = Object.assign({}, branch, {
        editable: !editable,
    });
    let updatedBranchs: Array<IBranch> = [];
    if (parentId === undefined) {
        const index = branchs.findIndex( (b: IBranch) => b.id === branch.id);
        updatedBranchs = Object.assign([], branchs, {
            [index]: updatedBranch,
        });
        onUpdateBranchs(updatedBranchs);
    } else {
        // EDIT: efforts 
        I'm tryin with this recursive method
    }
};
// EDIT
export const replaceBranch = (branchs: Array<IBranch>, branch: IBranch): Array<IBranch> => {
    let updated: Array<IBranch> = [];
    branchs.forEach((b: IBranch) => {
        if (b.children) {
            updated = replaceBranch(b.children, branch);
            if (updated) {
                return updated;
            }
        }
        if (b.id === branch.id) {
            const index: number = branchs.findIndex((c: IBranch) => c.id === branch.id);
            b.children[index] = branch;
            updated = b.children;
            console.log("founded: ", b);
            return updated;
        }
    });
    return updated;
};

And IBrach has this interface:

export interface IBranch {
    id: number;
    parentId: number | undefined;
    active: boolean;
    favorite: boolean;
    title: string;
    editable: boolean;
    level: number;
    checkbox: boolean;
    checkboxEnabled: boolean;
    children: Array<any>;
}

Data:

[
   {
      "id":0,
      "active":false,
      "favorite":false,
      "level":0,
      "title":"New Branch 0",
      "editable":false,
      "checkbox":false,
      "checkboxEnabled":false,
      "children":[
         {
            "id":1,
            "parentId":0,
            "active":false,
            "favorite":false,
            "level":1,
            "title":"New Branch 1",
            "editable":false,
            "checkbox":false,
            "checkboxEnabled":false,
            "children":[

            ]
         }
      ]
   }
]

enter image description here

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
Javier
  • 1,975
  • 3
  • 24
  • 46
  • 1
    Can you show us your efforts so far? – Scott Sauyet Jun 03 '20 at 13:52
  • of course, I've edited the question – Javier Jun 03 '20 at 13:55
  • 1
    Also very helpful would be a small set of sample data. A picture of it is not much help, I'm afraid. – Scott Sauyet Jun 03 '20 at 14:02
  • 1
    Please consider editing the code here to constitute a [mcve] suitable for dropping into a standalone IDE like [The TypeScript Playground](https://www.typescriptlang.org/play/). Right now there are errors with undefined/undeclared variables. If you're not asking about these errors, then please either add (or ideally remove) code to make them go away. Good luck! – jcalz Jun 03 '20 at 14:36

1 Answers1

3

I think you can do a fairly simple recursion here. I test with a very minimal set of data. Nodes have ids, titles, and sometimes children. But I think that's enough to show the behavior.

const updateElement = (obj, el) => 
  Array .isArray (obj) 
    ? obj .map (o => updateElement (o, el))
  : obj .id === el .id 
    ?  el
  : // else
    {...obj, ...(obj .children ? {children: updateElement (obj .children, el)} : {})}

const data = [
  {id: 1, title: 'foo', children: [
    {id: 11, title: 'bar'},
    {id: 12, title: 'baz', children: [
      {id: 121, title: 'qux'},
      {id: 122, title: 'quz'}
    ]},
    {id: 13, title: 'corge'}
  ]},
  {id: 2, title: 'grault'}
];

const newItem = {id: 121, title: 'new title here', and: 'more props'}

console .log (
  updateElement (data, newItem)
)
.as-console-wrapper {min-height: 100% !important; top: 0}

Note that this code doesn't stop searching on the first match. It checks everything and replaces all matches. I don't know if that's acceptable behavior for you.

This version is written in plain Javascript. I leave the Typescript typings to you. (Because I certainly don't want to do them!)

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • its perfect!! thanks a lot!! ... now I'm gonna try to insert an item recursively – Javier Jun 03 '20 at 15:19
  • export const addBranchInTree = ( branchs: any, branch: IBranch ): Array => { return Array.isArray(branchs) ? branchs.map((o: IBranch) => addBranchInTree(o, branch)) : branchs.children.push(branch); }; what do you think to add recursively? – Javier Jun 03 '20 at 15:27
  • It might work. You'd have to test, and looking at unformatted code in a comment is not one of my strengths! – Scott Sauyet Jun 03 '20 at 15:33
  • It seems to be missing something to test *where* to add an element. How do you decide? But really, if you struggle with this, it should probably be a new question instead of a series of comments. – Scott Sauyet Jun 03 '20 at 15:41
  • here is the question https://stackoverflow.com/questions/62177414/how-insert-item-in-tree-recursively – Javier Jun 03 '20 at 16:05