Reputation: 2645
I have a menu array called "items". It has submenus.
I need to filter the items with property "visible" equal 1. I don't know at run time how deep the hierarchy will be. I need a function returning a new array, with the next conditions:
My question is similar to this post Recursively filter array of objects.
But it does not work to me. I have used the following function, but it´s not working:
const items = [ { icon: "mdi-view-dashboard", title: "Dashboard", to: "/", visible: 1, },
{ title: "Manutenção", icon: "mdi-hammer-screwdriver", to: "", visible: 1,
items: [
{ title: "Usuários", icon: "mdi-account", to: "/usuarios", visible: 1, },
{ title: "Cores", to: "", visible: 1,
items: [
{ title: "Cores da Fila", icon: "mdi-eyedropper-variant", to: "/coresfila", visible: 1, },
{ title: "Cores da Agenda", icon: "mdi-palette", to: "/coresagenda", visible: 1, },
],
},
{ title: "Tabelas Médicas", to: "", visible: 1,
items: [
{ title: "Convênios", icon: "mdi-clipboard-outline", to: "/convenios", visible: 1, },
{ title: "Planos", icon: "mdi-plus-box", to: "/planos", visible: 1, },
{ title: "Especialidades", icon: "mdi-format-font", to: "/especialidadescompletas", visible: 1, },
{ title: "Modelos de Atestados", icon: "mdi-account-details-outline", to: "/modelosAtestados", visible: 1, },
{ title: "Modelos de Prescrições", icon: "mdi-account-edit-outline", to: "/modelosPrescricoes", },
{ title: "Cid-10", icon: "mdi-alphabetical", to: "/cid10", visible: 1, },
{ title: "Procedimentos", icon: "mdi-alarm-plus", to: "/procedimentos", visible: 1, },
{ title: "Materiais", icon: "mdi-table-of-contents", to: "/materiais", visible: 1, },
{ title: "Medicamentos", icon: "mdi-water", to: "/medicamentos", visible: 1, },
{ title: "Taxas", icon: "mdi-cash-100", to: "/taxas", visible: 1, },
],
},
],
},
{ title: "Empresa", icon: "mdi-cash-100", to: "", visible: 1,
items: [ { title: "Perfil da Empresa", icon: "mdi-account-network-outline", to: "/perfilempresa", visible: 1, },
{ title: "Créditos SMS", icon: "mdi-cash-usd-outline", to: "/creditossms", visible: 1, },
],
},
{ title: "Clientes", icon: "mdi-account-alert-outline", to: "/clientes", visible: 1, },
{ title: "Agenda", icon: "far fa-calendar-check", to: "/agenda", visible: 1, },
{ title: "Fila", icon: "mdi-account-multiple-check", to: "/fila", visible: 1, },
{ title: "Atendimento Médico", icon: "fas fa-user-md", to: "/atendimento", visible: 1, },
{ title: "Tela de Chamadas", icon: "mdi-play-network-outline", to: "/telao", visible: 1, },
{ title: "DICOM", icon: "mdi-radioactive-off", to: "/dicom", visible: 1, },
{ title: "Estatísticas", icon: "mdi-chart-box", to: "", visible: 1,
items: [ { title: "Clientes", icon: "mdi-account-arrow-right", to: "", visible: 1,
items: [ { title: "Por convênios", icon: "mdi-poll", to: "/estat_cliente_por_convenios", visible: 1, },
{ title: "Por mês", icon: "mdi-poll", to: "/estat_cliente_por_mes", visible: 1, },
],
},
{ title: "Faturamento", icon: "mdi-cash-usd", to: "", visible: 1,
items: [ { title: "Por convênios", icon: "mdi-poll", to: "/estat_faturamento_por_convenios", visible: 1, },
{ title: "Por mês", icon: "mdi-poll", to: "/estat_faturamento_por_mes", visible: 1, },
], },
], },
{ title: "Autorizações", icon: "mdi-microphone-variant", to: "/listaautorizacoes", visible: 1, },
{ title: "Faturamento", icon: "mdi-cash-usd", to: "", visible: 1,
items: [ { title: "Nova Guia", icon: "mdi-cart-plus", to: "/guiasfaturas", visible: 0, },
{ title: "Lista Guias", icon: "mdi-tray-plus", to: "/listaguias", visible: 1, },
{ title: "Lote de Guias", icon: "mdi-bag-personal", to: "/loteguias", visible: 1, }, ], },
]
function ofilter(arr) {
var matches = [];
if (!Array.isArray(arr)) return matches;
arr.forEach(function(i) {
if (i.visible && i.visible === 1) {
matches.push(i);
} else {
let childResults = this.ofilter(i.items);
if (childResults.length)
matches.push(Object.assign({}, i, {
items: childResults
}));
}
});
return matches;
}
console.log(ofilter(items))
Upvotes: 1
Views: 140
Reputation: 5956
Here's a recursive filter based on a recursive visibility check. This version preserves the nested structure:
const isVisible = item => item.visible
|| item.items?.some(isVisible)
const filterItems = items => {
items.forEach(item => {
if (item.items) item.items = filterItems(item.items)
})
return items.filter(isVisible)
}
console.log(filterItems(
[
{ id: 'a', visible: 1 },
{ id: 'b', visible: 0 },
{
id: 'c',
visible: 0,
items: [
{ id: 'd', visible: 1 },
{ id: 'e', visible: 0 }
]
},
{ id: 'f', visible: 1, items: [{ id: 'g', visible: 0 }] },
{ id: 'h', visible: 0, items: [{ id: 'i', visible: 0 }] },
]
))
Alternatively, here's a version that returns a flat array:
const filterItemsFlat = (items, results = []) => {
items.forEach(item => {
if (item.items) filterItemsFlat(item.items, results)
if (item.visible) results.push(item)
})
results.forEach(r => delete r.items)
return results
}
console.log(filterItemsFlat(
[
{ id: 'a', visible: 1 },
{ id: 'b', visible: 0 },
{
id: 'c',
visible: 0,
items: [
{ id: 'd', visible: 1 },
{ id: 'e', visible: 0 }
]
},
{ id: 'f', visible: 1, items: [{ id: 'g', visible: 0 }] },
{ id: 'h', visible: 0, items: [{ id: 'i', visible: 0 }] },
]
))
Upvotes: 1
Reputation: 2537
Another alternative to question:
const items = [
{ icon: "mdi-view-dashboard", title: "Dashboard", to: "/", visible: 1, },
{ title: "Manutenção", icon: "mdi-hammer-screwdriver", to: "", visible: 0,
items: [
{ title: "Usuários", icon: "mdi-account", to: "/usuarios", visible: 1, },
{ title: "Cores", to: "", visible: 0}
]
}
];
function ofilter(arr) {
let r = [];
arr.forEach((i) => {
if (i.visible == 1) {
r.push(i);
}
if (i.items) {
r.push(ofilter(i.items))
}
})
return r;
}
console.log('result:', ofilter(items))
Upvotes: 0