get path from JSON model - javascript

I already created dropdown menu. I have a problem with event press. I want get context from JSON when I press the menu.
JSON:
dropdownMenu: {
kepesertaan:[
{
name: "Menu1",
icon: "sap-icon://crop",
sub: [
{
name: "Submenu1-1",
icon: "sap-icon://create-session"
},
{
name: "Submenu1-2",
icon: "sap-icon://create-form"
}
]
},
{
name: "Menu2",
icon: "sap-icon://detail-view",
sub: [
{
name: "Submenu2-1",
icon: "sap-icon://add-activity"
},
{
name: "Submenu2-2",
icon: "sap-icon://action"
}
]
},
{
name: "Menu3",
icon: "sap-icon://delete",
sub: [
{
name: "Submenu3-1",
icon: "sap-icon://add-favorite"
},
{
name: "Submenu3-2",
icon: "sap-icon://add-document"
}
]
}
]
}
JS:
handleMenuItemPressKepesertaan: function(oEvent) {
var app = sap.ui.getCore().byId("menuEventingKepesertaan");
var oModel = app.getModel("kepesertaanmodel");
var oContext = oModel.getProperty("/1"); // get context from property by path
alert(oContext.name);
// alert(oContext.sub[0].name);
var bindingContext = sap.ui.getCore().getBindingContext();
var path = bindingContext.getPath();
alert(path);
}
I tried and alert path but failed. getPath() is not a function or undefined.
and this path will change the code "var oContext = oModel.getProperty("/1");". value "/1" is a path. and how to fix this problem? for information, the menu in fragment xml.

Related

Map an nested arrays and return matched ones

I know, there are already tons of same questions i saw some of them, but couldn't get full answer.
So, I have an array something like this (simplified for demonstration):
// links.js
const links = [
{
name: 'Page 1',
path: '/page-1'
},
{
name: 'Page-2',
subpages:[
{ name: 'Page (2-1)', path: '/page-2-1' },
{ name: 'Page (2-2)', path: '/page-2-2' }
]
},
{
name: 'Page 3',
path: '/page-3'
},
{
name: 'Page 4',
subpages:[
{ name: 'Page (4-1)', path: '/page-4-1' },
{ name: 'Page (4-2)', path: '/page-4-2' },
{ name: 'Page (4-3)', path: '/page-4-3' }
]
},
...
]
export default links
The above object is menu-links data, i render them on the screen for nagivating between pages and subpages is dropdown. They have either path or subpages, not both and there might be more nested.
There are 2 tasks i want help with.
First:
Every page of my site has a title and most of them is same as its name property shown above.
So, i have a function rendered on every page that returns the pathname of the current route, so what i want is to map through the links and get the name of matched path.
For example, if i give /page-4-1, i wanna get the name property of the matched path, So that is name: Page 4
Second
This time, it is something like a breadcrumb, If i give ['/page-1', '/page-2-1', '/page-4-2'], i wanna get:
[
{
name: 'Page 1',
path: '/page-1'
},
{
name: 'Page (2-1)',
path: '/page-2-1'
},
{
name: 'Page (4-2)',
path: '/page-4-2'
},
]
There will be cases where there might not be a matched result, in that case i would like to insert {name: document.body.title, path: null}
I tried
i'm using Nextjs
import { useRouter } from 'next/router'
import links from 'links.js'
const router = useRouter()
const splitted = router.asPath
.split('/')
.filter(
(sp) =>
sp !== ''
)
cost ready = []
for (let sp = 0; sp < splitted.length; sp++) {
for (let ln = 0; ln < links.length; ln++) {
if (links[ln].path) {
if (links[ln].path === '/' + splitted[sp]) {
ready.push(links[ln])
}
} else {
for (let sb = 0; sb < links[ln].sublinks.length; sb++) {
if (links[ln].sublinks[sb].path === '/' + splitted[sp]) {
ready.push(links[ln].sublinks[sb])
}
}
}
}
}
This is partly working but is messy, there should be a better ways with map, filter and find but i couldn't succeed with my tries on them.
Thank you in advance for your help!
EDIT:
Oops! my question had a big mistake, the links object only contains path key, not conditional path and link.
const links = [
{
name: 'Page 1',
path: '/page-1'
},
{
name: 'Page-2',
subpages:[
{ name: 'Page (2-1)', path: '/page-2-1' },
{ name: 'Page (2-2)', path: '/page-2-2' }
]
},
{
name: 'Page 3',
path: '/page-3'
},
{
name: 'Page 4',
subpages:[
{ name: 'Page (4-1)', path: '/page-4-1' },
{ name: 'Page (4-2)', path: '/page-4-2' },
{ name: 'Page (4-3)', path: '/page-4-3' }
]
},
];
const findPathObj = (path,links) => {
let result = null;
for(const item of links){
if(item.path == path) return item;
if(item.subpages) result = findPathObj(path, item.subpages)
if(result) break;
}
return result;
}
const findPageName = (path,links) => findPathObj(path,links)?.name;
const findBreadcrumb = (pathes, links) => pathes.map(path => findPathObj(path,links) || {name: document.title, path: null});
console.log(findPageName('/page-4-1', links));
console.log(findBreadcrumb(['/page-1', '/page-2-1', '/page-4-2'],links))
For your first question try the following
const links = [
{
name: "Page 1",
path: "/page-1",
},
{
name: "Page-2",
subpages: [
{ name: "Page (2-1)", path: "/page-2-1" },
{ name: "Page (2-2)", path: "/page-2-2" },
],
},
{
name: "Page 3",
link: "/page-3",
},
{
name: "Page 4",
subpages: [
{ name: "Page (4-1)", link: "/page-4-1" },
{ name: "Page (4-2)", link: "/page-4-2" },
{ name: "Page (4-3)", link: "/page-4-3" },
],
},
];
// Find out function
// Level must 0 at beginning
function findout(pages, search, level = 0) {
for (const page of pages) {
if (page.link === search || page.path === search) {
if (level === 0) {
return page.name;
}
return true;
}
if (Array.isArray(page.subpages)) {
if (findout(page.subpages, search, level + 1)) {
if (level === 0) {
return page.name;
}
return true;
}
}
}
return false;
}
console.log(findout(links, "/page-4-3"))
The second question I suggest this
const links = [
{
name: "Page 1",
path: "/page-1",
},
{
name: "Page-2",
subpages: [
{ name: "Page (2-1)", path: "/page-2-1" },
{ name: "Page (2-2)", path: "/page-2-2" },
],
},
{
name: "Page 3",
link: "/page-3",
},
{
name: "Page 4",
subpages: [
{ name: "Page (4-1)", link: "/page-4-1" },
{ name: "Page (4-2)", link: "/page-4-2" },
{ name: "Page (4-3)", link: "/page-4-3" },
],
},
];
function findout2(pages, search, result = []) {
for (const page of pages) {
if (typeof page.link === "string" && search.includes(page.link)) {
result.push({ name: page.name, link: page.link });
} else if (typeof page.path === "string" && search.includes(page.path)) {
result.push({ name: page.name, path: page.path });
}
if (Array.isArray(page.subpages)){
findout2(page.subpages, search, result)
}
}
return result
}
console.log(findout2(links, ['/page-1', '/page-2-1', '/page-4-2']))

Filter custom JSON

I have this JSON
const Menu = [{
icon: "home",
text: "Inicio",
url: {
name: "home"
},
typeUrl: "exact"
},
{
heading: "Operaciones"
},
{
icon: "settings",
"icon-alt": "settings",
text: "Operación",
model: true,
children: [{
icon: "add",
text: "Cargar Pedidos",
url: {
name: "cargarpedidos"
}
},
{
icon: "playlist_add_check",
text: "Aprobar Pedidos"
},
{
icon: "content_copy",
text: "Remitir Pedidos"
}
]
},
{
heading: "Informes"
},
{
icon: "widgets",
"icon-alt": "widgets",
text: "Informe",
model: false,
children: [{
icon: "view_module",
text: "Usuarios"
},
{
icon: "view_module",
text: "Perfiles"
},
{
icon: "view_module",
text: "Permisos Perfiles"
},
{
icon: "view_module",
text: "Resetear Password"
},
{
icon: "view_module",
text: "Cambiar Password"
}
]
},
{
heading: "APSI"
},
{
icon: "view_module",
text: "Informes del APSI"
},
{
heading: "Administaciones"
},
{
icon: "extension",
"icon-alt": "extension",
text: "Administración",
model: false,
children: [{
icon: "face",
text: "Usuarios"
},
{
icon: "assignment_ind",
text: "Perfiles"
},
{
icon: "settings",
text: "Permisos Perfiles"
},
{
icon: "cached",
text: "Resetear Password"
},
{
icon: "fingerprint",
text: "Cambiar Password"
}
]
},
{
heading: "Mantenimientos"
},
{
icon: "build",
"icon-alt": "build",
text: "Mantenimiento",
model: true,
children: [{
icon: "group_work",
text: "Departamentos"
},
{
icon: "room",
text: "Locales"
},
{
icon: "donut_large",
text: "Unidades de Medida"
},
{
icon: "spellcheck",
text: "Articulos"
},
{
icon: "toc",
text: "Categorías"
},
{
icon: "supervisor_account",
text: "Usuario Aprobador"
}
]
}
];
export default Menu;
I use it to create the menu of my system that I am developing with VueJS + Vuetify and I need to filter it through the "text" field by words that contain it regardless of position, in the style of SQL's like '%filter%', also without distinguish upper and lower case. As far as possible don't distinguish accents (but this is already very picky, if it is not possible or it is very cumbersome, I can skip it).
Also in the case that the pattern of coincidence is in a child node and not in the father, does this father also have to appear in the filter, is it possible to do this with a Javascript function?
The menu looks like this:
I expect this behavior
I am not sure but if you want to get text fields of children, I think something like that should do it. You just need to initialize all your parents with empty children arrays:
tempArr = Menu.filter(function (elem) {
return elem.children == null ;
});
textFields = tempArr.map(({ text }) => text)
Here is how you can filter match regular expression in an array.
var arr = [{
icon: "add",
text: "Cargar Pedidos",
url: {
name: "cargarpedidos"
}
},
{
icon: "playlist_add_check",
text: "Aprobar Pedidos"
},
{
icon: "content_copy",
text: "Remitir Pedidos"
},
{
icon: "content_copy",
text: "Remitir Pedisddos"
},
{
icon: "content_copy",
text: "Remitir Pediados"
},
{
icon: "content_copy",
text: "Remitir asdaasd"
}
];
var name = "dido";
var regex = "/" + name + "/g";
var filtered = arr.filter(
(val) => val.text.match(name)
);
console.log(filtered);
These are the basics of filtering. If you want to search for any property in an array object than use this function:
var result = Menu.filter(function(o) {
return Object.keys(o).some(function(k) {
return o[k].toString().toLowerCase().indexOf('dido') != -1;
})
})
console.log(result)

Filtering and appending in JSON?

I have a JSON variable in React like this:
var newTreeData_2 = {
name: current_name,
img: current_img,
uuid: uuid.v4(),
children: [
{
name: "Edit and save",
img:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: uuid.v4()
},
{
name: "add a new one",
img:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: uuid.v4()
}
]
};
Each uuid.v4() is a unique ID.
What I want to do is to make a function which takes in a UUID, and should append a new object children:[{}] to where the UUID is located at. For example, if **my uuid matches the uuid.v4() on line 10 of the code snippet, it should append a JSON object so the end result looks like:
var newTreeData_2 = {
name: current_name,
img: current_img,
uuid: uuid.v4(),
children: [
{
name: "Edit and save",
img:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: uuid.v4(),
chilren: [{}]
},
{
name: "add a new one",
img:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: uuid.v4()
}
]
};
this recursive function find object with target UUID and add children to them
var newTreeData = {
name: 'a',
img: 'b',
uuid: 1234,
children: [{
name: "Edit and save",
img: "https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: 12345,
children: [{
name: "Edit and save",
img: "https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: 123
}]
},
{
name: "add a new one",
img: "https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: 132456
}
]
};
function findUUID(targetObject, uuid) {
var children = targetObject.children;
if (!!children === false) return;
var target = children.filter(x => {
if (x.uuid === uuid) return x;
});
if (target.length === 0) {
children.map(x => findUUID(x, uuid));
} else {
if (!!target[0].children && target[0].children.length !== 0) {
target[0].children.push({});
console.log(target);
} else {
target[0].children = [{}];
console.log(target);
}
}
}
findUUID(newTreeData, 132456);
As I understand it, you want to add an object if the child's uuid is equal to a given uuid.
If that's what you want, you can loop through each child, test if it's uuid is equal to the given uuid, and if it is, add [{}].
function addJSONObjct(obj, uuid) {
for (i = 0; i < obj.children.length; i ++) {
if (obj.children[i].uuid === uuid) {
obj.children[i].children=[{}];
}
}
}
The exact code i have to solve this problem:
findUUID(targetObject, uuid2, name, img, details) {
var targetIsFound = false;
var target = "";
console.log("Parent TreeData UUID" + targetObject.uuid);
console.log("UUID we are trying to match" + uuid2);
if (targetObject.uuid == uuid2) {
targetIsFound = true;
target = targetObject;
}
console.log(targetIsFound, target);
if (targetIsFound == false) {
console.log(
"About to start recursion, this is the target Object: ",
targetObject
);
if (targetObject.children === undefined) {
console.log("we should exit here");
} else {
targetObject.children.map(x => this.findUUID(x, uuid2));
}
} else {
if (target.name == "Edit and save") {
target.children = [
{
name: "Edit and save",
img:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: uuid.v4()
},
{
name: "Edit and save",
img:
"https://cdn3.iconfinder.com/data/icons/harmonicons-06/64/plus-circle-512.png",
uuid: uuid.v4()
}
];
}
this.setState({ treeData: this.state.treeData });
console.log(this.state.treeData);
}
}
name, img and details are just parameters to fill the data with the uuids matched. The reason I named the matching uuid "uuid2" is because I imported the uuid package and there can be conflicts.
Jeff and Barzin's code work, If your data is like mine you have to run recursion on Jeff's method. My code is different from Barzin's in that I am doing an error check: if(targetObject.children === undefined) to make sure I don't continue to perform recursion if there is nothing to perform it with. By the way, this method puts assumption that the UUID we are trying to find definitely exists in targetObject.

How to get states from a Vuex store from within a Vuetify list, VueJs

I have a Vue file that looks like so :
import store from '#/store'
export default{
name: 'myList',
data: () => ({
show: true,
listContent: [{
name: '1',
icon: 'person',
value: function () {
return store.state.myStore.settings.one
}
}, {
name: '2',
icon: 'person',
value: function () {
return store.state.myStore.settings.two
}
}, {
name: '3',
icon: 'person',
value: function () {
return store.state.myStore.settings.three
}
}
]
})
}
The part that's not working is getting the 'value' from the 'listContent'.
{
name: '3',
icon: 'person',
value: function () {
return store.state.myStore.settings.three
}
}
In my code, I have imported the view as if I were to put :
this.$store.state.myStore.settings.one
Inside the value function, 'this' would refer to the object
{
name: '3',
icon: 'person',
value: function () {
return store.state.myStore.settings.three
}
}
And I wouldnt be able to get the store. However, my code still doesn't work. I need to get access to the store inside the listContent.
The list is rendered like so :
<v-data-table :items="listContent" hide-actions hide-headers>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right" v-text="props.item.value()"> </td>
</template>
</v-data-table>
Either I have referenced the store incorrectly, or the template is incorrect. Any ideas ?
Why do you want the value to be a function that returns the state value. You can just assign it to state value using this.$store.state.myStore.settings.one
For this to work make the data option a normal function instead of an arrow function so that this still represents the vue instance
export default {
name: "myList",
data() {
return {
show: true,
listContent: [
{
name: "1",
icon: "person",
value: this.$store.state.myStore.settings.one
},
{
name: "2",
icon: "person",
value: this.$store.state.myStore.settings.two
},
{
name: "3",
icon: "person",
value: this.$store.state.myStore.settings.three
}
]
};
}
};
May be this will help. Long one, but it works.
const myModule = {
state: {
test: "modulle",
settings: {
one: "This is one",
two: "This is two",
three: "This is three"
}
}
};
const store = new Vuex.Store({
modules: { myModule }
});
new Vue({
el: "#app",
store,
data() {
return {
listContent: [
{
name: "1",
icon: "person",
value: null
},
{
name: "2",
icon: "person",
value: null
},
{
name: "3",
icon: "person",
value: null
}
]
};
},
watch:{
'$store.state.myModule.settings.one':{
immediate:true,
handler:function(value){
this.listContent[0].value = value;
}
},
'$store.state.myModule.settings.two':{
immediate:true,
handler:function(value){
this.listContent[1].value = value;
}
},
'$store.state.myModule.settings.three':{
immediate:true,
handler:function(value){
this.listContent[2].value = value;
}
},
}
});

ES6 get properties from nested objects

i'm doing a project with VueJS, Lodash and Babel, and my problem is that i need to populate a sidebar in my app with routes from a routes.js file. Problem is i don't really know how i can retrieve the data i need.
export default [
{
path: "/admin/login",
name: "admin.login",
component: Login
},
{
path: "/admin",
component: MasterLayout,
meta: { auth: true },
children: [
{
path: "/admin/dashboard",
alias: "/",
menu: { text: "", icon: ""},
name: "admin.dashboard",
component: DashboardIndex
}
]
},
{
path: '/403',
name: 'error.forbidden',
component: ErrorForbidden
},
{
path: "*",
name: 'error.notfound',
component: ErrorPageNotFound
}
];
That is my routes file, i basically need to iterate over each route, check if it has children or a menu property, if it has a menu it gets added to my list of sidebar items, and it's children get added as well with their own menu properties being withdrawn
In the end i'd like to get something like the following
sidebarItems: [
{
name: 'Dashboard',
icon: 'dashboard',
name: 'admin.dashboard'
},
{
name: 'OtherRoute',
icon: 'other-route',
name: 'admin.other-route',
children: [
{
name: 'SubRoute',
icon: 'sub-route',
name: 'admin.sub'
}
]
}
]
This should only account for the routes that contain a menu property.
You basically need iterate recursive over the array, so please try this:
function iterateArrayRoutes(routeArray) {
if(routeArray instanceof Array) {
var routeFormatted = routeArray.reduce(function(last, route){
if (route.hasOwnProperty("menu")) {
var item = {
name: route.name,
icon: route.menu.icon
};
if(route.hasOwnProperty("children") && route.children.length > 0) {
item.children = iterateArrayRoutes(route.children);
}
last.push(item);
}
return last;
}, []);
return routeFormatted;
}
};
Here you have a Demo https://jsfiddle.net/vm1hrwLL/

Categories