Angular menu items with attached dropdowns doesn't display at all - javascript

I'm making an angular menu which is pretty complex (or will be later on), I've done most of the structuring but I'm stuck on this one thing. As you can see I have specified different menu options for different people depending on who's currently logged in. Right now I just want to show the menu for the "admin". I've put an ng-if that checks for an admin property, if it find one it should loop out it's contents as a main li item along with an ul containing the dropdown list items. However the way I've done it it shows everything excepts the admin content.. I've been trying different solutions for hours but I just can't get it right. What am I doing wrong?
I apologize for a lot of code but it's necessary to get a good overview of the structure I have.
<header>
<ul id="main-menu">
<li data-ng-repeat="menu in menus" id="{{menu.id}}">{{menu.title}}
<ul data-ng-repeat="submenu in menu" data-ng-if="menu.admin"> <--if admin
<li data-ng-repeat="subitem in submenu.items">{{subitem.title}}</li>
</ul>
</li>
</ul>
</header>
This is my controller containing all the information:
onlinePlatform.controller('onlinePlatformCtrl', function ($scope) {
$scope.menus = [
{
title: 'Startsida',
URL: 'home'
},
{
title: 'Nyheter',
URL: 'news'
},
{
title: 'Meddelanden',
items: [
{
title: 'Inkorg',
URL: 'inbox'
},
{
title: 'Skickade meddelanden',
URL: 'sentmsg'
},
{
title: 'Borttagna meddelanden',
URL: 'removedmsg'
}
],
URL: 'messages',
id: 'msg'
},
{
admin: {
title: 'Administration',
items: [
{
title: 'Hantera utbildningar',
URL: 'mngprograms'
},
{
title: 'Hantera kurser',
URL: 'mngcourses'
},
{
title: 'Hantera lärare',
URL: 'mngteachers'
},
{
title: 'Hantera studenter',
URL: 'mngstudents'
}
],
URL: 'administration',
id: 'administration'
},
teacher: {
title: 'Utbildning',
items: [
{
title: 'Kurser överblick',
URL: 'coursesoverview'
},
{
title: 'Sätt eller ändra betyg',
URL: 'editgrades'
},
{
title: 'Boka eller avboka lokaler',
URL: 'classroombooking'
}
],
URL: 'utbildning',
id: 'utbildning'
},
student: {
title: 'Mina sidor',
items: [
{
title: 'Mina kurser',
URL: 'mycourses'
},
{
title: 'Mitt schema',
URL: 'myschedule'
},
{
title: 'Mina betyg',
URL: 'mygrades'
},
{
title: 'Mina kontaktuppgifter',
URL: 'mycontactinfo'
},
{
title: 'Klasslista',
URL: 'classlist'
},
{
title: 'Anteckningar',
URL: 'notes'
}
],
URL: 'mypages',
id: 'mypages'
}
},
{
title: 'Forum',
URL: 'forum'
},
{
title: 'Kalender',
URL: 'calendar'
},
{
admin: {
title: 'Enkäter',
items: [
{
title: 'Skapa enkät',
URL: 'createsurvey'
},
{
title: 'Visa tidigare enkäter',
URL: 'previussurveys'
}
],
URL: 'surveys',
id: 'surveys'
},
teacher: {
title: 'Kontaktuppgifter',
items: [
{
title: 'Profil',
URL: 'profile'
},
{
title: 'Redigera kontaktuppgifter',
URL: 'editcontactinfo'
}
],
URL: 'contactinfo',
id: 'contactinfo'
},
student: {
title: 'Verktyg',
items: [
{
title: 'Ladda ner Dreamspark produkter',
URL: 'dreamspark'
}
],
URL: 'tools',
id: 'tools'
}
},
{
title: 'Hjälp',
items: [
{
title: 'Vanliga frågor',
URL: 'faq'
},
{
title: 'JENSEN kontaktuppgifter',
URL: 'contactinfo'
}
],
URL: 'help',
id: 'help'
}
]
});

Use this, ng-show=menu.admin. However, it's advised to use a method rather than just an assignment to check the authorization to show/hide elements, as the method will wait until Angular resolves it's value but the variable just consider it's current status to show/hide the element.

Related

How to map through an object and return a component based on object keys in react

I have an objects of object and I want to loop through it and display it based on the key.
Input:
export let data = {
home: {
title: "home",
url: "/home"
},
dashboard: {
title: "dashboard",
url: "/dashboard"
},
pages: {
title: "pages",
url: "/pages"
},
subpages: {
title: "subpages",
url: "/pages/subpages"
},
login: {
title: "login",
url: "/pages/login"
},
account: {
title: "account",
url: "/dashboard/account"
}
}
if URL is a sub url of other object then it should be displayed below it.
Expected output:
Home
dashboard
account
pages
subpages
login
It should be displayed like this but in say <h2> and <p>
You could do this by building up a hierarchy using reduce.
let data = {
home: {
title: "home",
url: "/home"
},
dashboard: {
title: "dashboard",
url: "/dashboard"
},
pages: {
title: "pages",
url: "/pages"
},
subpages: {
title: "subpages",
url: "/pages/subpages"
},
login: {
title: "login",
url: "/pages/login"
},
account: {
title: "account",
url: "/dashboard/account"
}
}
var result = Object.entries(data).reduce((acc,[key,{title,url}]) => {
const parts = url.substring(1).split("/");
let obj = acc;
for(var i=0;i<parts.length;i++){
if(!obj[parts[i]]) obj[parts[i]] = {}
obj = obj[parts[i]];
}
obj.url = url;
return acc;
},{});
console.log(result);
Hey this code snipped can help
let data = {
home: {
title: "home",
url: "/home"
},
dashboard: {
title: "dashboard",
url: "/dashboard"
},
pages: {
title: "pages",
url: "/pages"
},
subpages: {
title: "subpages",
url: "/pages/subpages"
},
login: {
title: "login",
url: "/pages/login"
},
account: {
title: "account",
url: "/dashboard/account"
}
}
Object.entries(data).map(([key, value]) => {
console.log(key);
})

JavaScript: Best way for update all tree items?

I try to create sidebar component in React and I have a data structure like bellow
const links = [
{
label: 'Item-1',
url: '/item-1',
},
{
label: 'Item-2',
children: [
{
label: 'Item-2-1',
url: '/item-2-1',
},
{
label: 'Item-2-2',
url: '/item-2-2',
},
{
label: 'Item-2-3',
url: '/item-2-3',
},
],
},
{
label: 'Item-3',
children: [
{
label: 'Item-3-1',
url: '/item-3-1',
},
{
label: 'Item-3-2',
url: '/item-3-2',
},
],
},
];
So the problem is let's say the user changed URL and URL something like that http://localhost:90/item-2-3.
And I need to activate this sidebar item from the sidebar and it can be nested. So firstly I need to deactivate all other sidebar items (I don't want multiple selected items in the sidebar) and after that activate the selected sidebar item.
Because that (if I'm correct) I need update all tree items let's say I add active:false field to all JSON and after that I need to find the correct tree item from tree (URL === item-2-3) add active:true and also update all parent json to active:true (for there are look selected/opened)
So my question is am I correct if I correct how can write this code optimal way? :/
Actually, I want to create a function and when calling this function like that selectItemFromTree(links, '/item-2-2') I get results like in bellow.
const links = [
{
label: 'Item-1',
url: '/item-1',
active: false
},
{
label: 'Item-2',
active: true,
children: [
{
label: 'Item-2-1',
url: '/item-2-1',
active: false
},
{
label: 'Item-2-2',
url: '/item-2-2',
active: true,
},
{
label: 'Item-2-3',
url: '/item-2-3',
active: false
},
],
},
{
label: 'Item-3',
active: false,
children: [
{
label: 'Item-3-1',
url: '/item-3-1',
active: false
},
{
label: 'Item-3-2',
url: '/item-3-2',
active: false
},
],
},
];
You have to traverse the tree recursively and update all the active statuses.
const links=[{label:"Item-1",url:"/item-1"},{label:"Item-2",children:[{label:"Item-2-1",url:"/item-2-1"},{label:"Item-2-2",url:"/item-2-2"},{label:"Item-2-3",url:"/item-2-3"}]},{label:"Item-3",children:[{label:"Item-3-1",url:"/item-3-1"},{label:"Item-3-2",url:"/item-3-2"}]}];
const updateActiveLink = (links, url, parent = null) => {
for (link of links) {
link.active = false;
if (link?.children) {
updateActiveLink(link.children, url, link)
}
if (link.url === url) {
link.active = true;
if (!!parent) parent.active = true;
}
}
}
updateActiveLink(links, '/item-2-3');
console.log(links);
.as-console-wrapper {min-height: 100%!important; top: 0}
Note that this method will mutate the links array.

Sanity CMS, referencing arrays within a document

My goal is to have a custom internalLink mark that is able to reference not just the post (which is easy enough since its a type: document) but also reference name: sections which returns array of section.js. That way editors can link to any section within a post document. And ideally the editors can also reach other post sections as well, not just the current one open.
I want to be able to reference the following collection of section.js in the reference dropdown:
Now I understand reference only works for type: document. Can I make it work for the children (array or object) of type: post?
My custom block.js
marks: {
...
annotations: [
{
name: "internalLink",
title: "Internal link",
type: "object",
fields: [
{
name: "linkto",
type: "reference",
title: "Link To",
to: [{ type: "post" }],
},
],
},
...
post.js
export default {
name: "post",
title: "Document",
type: "document",
fields: [
...
{
name: "sections",
title: "Sections",
type: "array",
of: [{ type: "section" }],
},
],
}
section.js
export default {
title: "Section",
name: "section",
type: "object",
fields: [
{
name: "sectionTitle",
title: "Section Title",
type: "string",
},
{
title: "Content",
name: "content",
type: "blockContent",
},
],
}
Appreciate any help/pointers I can get :)

Created item can not be edited or deleted without a grid refresh in ShieldUI

I want to use the ShieldUI library (grid component) in order to present tabular data to the user.
The issue with this library is that if I create a new item and right after I want to edit or delete it, the grid is unable to provide its id (as the database generates for me), although I return the id from backend after the INSERT query is executed. Here is what I tried:
<!-- HTML and JS part -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery Shield UI Demos</title>
<link id="themecss" rel="stylesheet" type="text/css" href="//www.shieldui.com/shared/components/latest/css/light/all.min.css" />
<script type="text/javascript" src="//www.shieldui.com/shared/components/latest/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="//www.shieldui.com/shared/components/latest/js/shieldui-all.min.js"></script>
</head>
<body class="theme-light">
<div id="grid"></div>
<script type="text/javascript">
$(document).ready(function () {
$("#grid").shieldGrid({
dataSource: {
remote: {
read: "/products",
modify: {
create: {
url: "/products/productCreate",
type: "post",
data: function (edited) {
var date = edited[0].data.AddedOn ? edited[0].data.AddedOn.toJSON() : new Date().toJSON();
return {
Active: edited[0].data.Active,
AddedOn: date,
Category: edited[0].data.Category,
Name: edited[0].data.Name,
Price: edited[0].data.Price,
Id: edited[0].data.Id
};
}
},
update: {
url: "/products/productUpdate",
type: "post",
data: function (edited) {
var date = edited[0].data.AddedOn ? edited[0].data.AddedOn.toJSON() : new Date().toJSON();
return {
Active: edited[0].data.Active,
AddedOn: date,
Category: edited[0].data.Category,
Name: edited[0].data.Name,
Price: edited[0].data.Price,
Id: edited[0].data.Id
};
}
},
remove: {
url: "/products/productRemove",
type: "post",
data: function (removed) {
return { id: removed[0].data.Id };
}
}
}
},
schema: {
fields: {
Id: { path: "Id", type: Number },
Price: { path: "Price", type: Number },
Name: { path: "Name", type: String },
Category: { path: "Category", type: String },
AddedOn: { path: "AddedOn", type: Date },
Active: { path: "Active", type: Boolean }
}
}
},
rowHover: false,
columns: [
{ field: "Name", title: "Product Name", width: "300px" },
{ field: "Price", title: "Price", width: "100px" },
{ field: "Category", title: "Category", width: "200px" },
{ field: "AddedOn", title: "Added On", format: "{0:MM/dd/yyyy}" },
{ field: "Active", title: "Active" },
{
title: " ",
width: "100px",
buttons: [
{ cls: "deleteButton", commandName: "delete", caption: "<img src='/Content/img/grid/delete.png' /><span>Delete</span>" }
]
}
],
editing: {
enabled: true,
event: "click",
type: "cell",
confirmation: {
"delete": {
enabled: true,
template: function (item) {
return "Delete row with ID = " + item.Id
}
}
}
},
toolbar: [
{
buttons: [
{ commandName: "insert", caption: "Add Product" }
],
position: "top"
}
]
});
});
</script>
<style>
.deleteButton img
{
margin-right: 3px;
vertical-align: bottom;
}
</style>
</body>
</html>
Below is the ASP.MVC part:
[ActionName("productCreate")]
public Product PostProduct(Product item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
item.Id = Products.Max(i => i.Id) + 1;
Products.Add(item);
return item;
}
To make this work, I need to refresh the grid's content by performing a sort operation (the framework updates the grid before sorting) or worse, a page refresh.
So what is the issue with this approach? Am I missing something?
We need to modify the create object and use AJAX call in order to make this work.
So instead of:
create: {
url: "/products/productCreate",
type: "post",
data: function (edited) {
var date = edited[0].data.AddedOn ? edited[0].data.AddedOn.toJSON() : new Date().toJSON();
return {
Active: edited[0].data.Active,
AddedOn: date,
Category: edited[0].data.Category,
Name: edited[0].data.Name,
Price: edited[0].data.Price,
Id: edited[0].data.Id
};
}
}
You have to do:
create: function (items, success, error) {
var newItem = items[0];
$.ajax({
type: "POST",
url: "/products/productCreate",
dataType: "json",
data: newItem.data,
complete: function (xhr) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
// update the id of the newly-created item with the
// one returned from the server
newItem.data.Id = xhr.responseJSON.Id;
success();
return;
}
}
error(xhr);
}
});
}

show a nested Json on EXT.dataview.List

I was not able to show <div>{lat}, {lon}, {ele}</div> on a sencha touch usingEXT.dataview.List ItemTpl with data from a Json File:
Json:
{
"data": {
"trackData":
[
{
"lon": 9.979255199432373,
"lat": 53.56595538391044,
"ele": 19
},
{
"lon": 9.973998069763184,
"lat": 53.56923037464335,
"ele": 15
}
]
}
}
Model:
Ext.define('Fahrradtour.model.Location', { extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'lat',
type: 'float'
},
{
name: 'lon',
type: 'float'
},
{
name: 'ele',
type: 'float'
}
]
}
});
Store:
Ext.define('Fahrradtour.store.LocationStore', { extend: 'Ext.data.Store',
requires: [
'Fahrradtour.model.Location'
],
config: {
autoLoad: true,
model: 'Fahrradtour.model.Location',
storeId: 'LocationStore',
proxy: {
type: 'ajax',
url: './data/json-track.json',
reader: {
type: 'json',
rootProperty: 'data',
record: 'trackData'
}
}
}
});
the Store loads his data in Architect well, but the List shows nothing.
anybody has an Idea what is wrong?
thanks.

Categories