0

My navigation gets the routes from the vue-router, so that I do not have to add them manually.

These routes have a meta boolean key called "inMenu", as well as their child routes. I only manage to filter the parent routes but not the child routes.

var res = this.$router.options.routes.filter(function f(o) {
  if (o.route.meta.inMenu === true) return true

  if (o.children) {
    return (o.children = o.children.filter(f)).length
  }
})

This is how I filter the parent routes but I can't manage it to filter the children.

return this.$router.options.routes.filter(route => route.meta.inMenu === true);

This is some sample data:

{
  "path": "/orders",
  "component": {
    "name": "Orders",
    "__file": "src/views/Orders.vue",
  },
  "meta": {
    "icon": "fa-history",
    "title": "Abwicklungen",
    "inMenu": true
  },
  "children": [
    {
      "path": "list",
      "name": "orderList",
      "component": {
        "name": "OrderList",
        "__file": "src/views/orders/list.vue",
      },
      "meta": {
        "title": "Bestellliste",
        "icon": "fa-circle-o",
        "inMenu": true
      }
    },
    {
      "path": "details/:id",
      "name": "orderDetails",
      "component": {
        "name": "OrderDetails",
        "__file": "src/views/orders/details.vue"
      },
      "meta": {
        "title": "Bestellung",
        "icon": "fa-circle-o",
        "inMenu": false
      }
    },
    {
      "path": "dailyclosing",
      "component": {
        "name": "OrderList",
        "__file": "src/views/orders/list.vue",
      },
      "meta": {
        "title": "Tagesabschluss",
        "icon": "fa-check",
        "inMenu": true
      }
    }
  ]
}

I want to have each route and children not shown if inMenu is false.

Kazuto
  • 158
  • 2
  • 15
  • Could you provide sample data and show for that data your expected result? – claasic Aug 09 '19 at 08:42
  • 2
    do you intentionally mutate the given data? – Nina Scholz Aug 09 '19 at 08:43
  • the 5th line: `return (o.children = o.children.filter(f)).length` has an assignment. is it intentionaly? – Mr. Aug 09 '19 at 08:43
  • 1
    assoron: I've added sample data to my question. NinaScholz: It's the only thing I came up with xD Mr.: This was an answer by this post but it did not work, even thought they're example worked. https://stackoverflow.com/questions/38132146/recursively-filter-array-of-objects – Kazuto Aug 09 '19 at 08:53
  • I am assuming that the object provided is one of many inside an array? Also if the parent is false, should all children be removed too or do you still want to return the filtered children without parent information? – claasic Aug 09 '19 at 08:57
  • please add some data with various possibilities and the wanted result. for example do you want false inMenu items, but with true children, or all true or only true ends? – Nina Scholz Aug 09 '19 at 09:01
  • @assoron No, if a parent is false the children should not be returned. But that would just be a if statement before it even goes through children, so that's not really a problem :D – Kazuto Aug 09 '19 at 09:27
  • @Kazuto That's how I implemented it, see below :) – claasic Aug 09 '19 at 09:32

3 Answers3

1

I am assuming:

  1. You have multiple path objects inside an array.
  2. Each path object contains a root level meta key and a children key.
  3. If the inMenu value of the root meta key returns false, we filter out the whole object (which includes its children).
  4. children doesn't contain any more children on its own .

So we apply reduce on the array, check whether the object's root inMenu is true and if so it will reconstruct itself while filtering its children. Filtering the children happens via the short helper function.

var data = [{"path":"/orders","component":{"name":"Orders","__file":"src/views/Orders.vue",},"meta":{"icon":"fa-history","title":"Abwicklungen","inMenu":!0},"children":[{"path":"list","name":"orderList","component":{"name":"OrderList","__file":"src/views/orders/list.vue",},"meta":{"title":"Bestellliste","icon":"fa-circle-o","inMenu":!0}},{"path":"details/:id","name":"orderDetails","component":{"name":"OrderDetails","__file":"src/views/orders/details.vue"},"meta":{"title":"Bestellung","icon":"fa-circle-o","inMenu":!1}},{"path":"dailyclosing","component":{"name":"OrderList","__file":"src/views/orders/list.vue",},"meta":{"title":"Tagesabschluss","icon":"fa-check","inMenu":!0}}]}];

const f = arr => arr.filter(o => o.meta.inMenu);

let res = data.reduce((a,c) => (c.meta.inMenu && a.push({...c, children: f(c.children)}), a),[]);

console.log(res)
claasic
  • 1,050
  • 6
  • 14
1

Assuming you want all objects with true inMenu properties, you could build a new array with new children. Branches with no true inMenu items are filterd out.

function filter(array) {
    return array.reduce((r, { children = [], ...o }) => {
        children = filter(children);
        if (o.meta.inMenu || children.length) r.push(Object.assign({}, o, children.length && { children }));
        return r;
    }, [])
}

var data = [{ path: "/orders", meta: { icon: "fa-history", title: "Abwicklungen", inMenu: true }, children: [{ path: "list", name: "orderList", meta: { title: "Bestellliste", icon: "fa-circle-o", inMenu: true } }, { path: "details/:id", name: "orderDetails", meta: { title: "Bestellung", icon: "fa-circle-o", inMenu: false } }, { path: "dailyclosing", meta: { title: "Tagesabschluss", icon: "fa-check", inMenu: true } }] }, { path: "/orders", meta: { icon: "fa-history", title: "Abwicklungen", inMenu: false }, children: [{ path: "list", name: "orderList", meta: { title: "Bestellliste", icon: "fa-circle-o", inMenu: true } }, { path: "details/:id", name: "orderDetails", meta: { title: "Bestellung", icon: "fa-circle-o", inMenu: false } }, { path: "dailyclosing", meta: { title: "Tagesabschluss", icon: "fa-check", inMenu: true } }] }],
    result = filter(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Here is a working snippet. I think you just need to update your function in a way I have changed it. Of-course I have not use vue.js routes here. This is just a sample. You need to update according to your need. I think you'll get idea from here, about what is wrong in your function.

var data = [{
  "path": "/orders",
  "component": {
    "name": "Orders",
    "__file": "src/views/Orders.vue",
  },
  "meta": {
    "icon": "fa-history",
    "title": "Abwicklungen",
    "inMenu": true
  },
  "children": [
    {
      "path": "list",
      "name": "orderList",
      "component": {
        "name": "OrderList",
        "__file": "src/views/orders/list.vue",
      },
      "meta": {
        "title": "Bestellliste",
        "icon": "fa-circle-o",
        "inMenu": true
      }
    },
    {
      "path": "details/:id",
      "name": "orderDetails",
      "component": {
        "name": "OrderDetails",
        "__file": "src/views/orders/details.vue"
      },
      "meta": {
        "title": "Bestellung",
        "icon": "fa-circle-o",
        "inMenu": false
      }
    },
    {
      "path": "dailyclosing",
      "component": {
        "name": "OrderList",
        "__file": "src/views/orders/list.vue",
      },
      "meta": {
        "title": "Tagesabschluss",
        "icon": "fa-check",
        "inMenu": true
      }
    }
  ]
}];


var res = data.filter(function f(o) {
  if (o.children) {
    return (o.children = o.children.filter(f)).length
  }
  if (o.meta.inMenu === true) return true;
  return false;
})

console.log(res);
Mazedul Islam
  • 1,543
  • 1
  • 11
  • 15