API call or JS function to get a list of categories and URL's
-
Odd...
How come this works
$.get('/api/categories').then(d => console.log(d.categories)); {state: ƒ, always: ƒ, catch: ƒ, pipe: ƒ, then: ƒ, …} VM406:1 (7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]0: {cid: 2, name: 'General Discussion', description: 'A place to talk about whatever you want', icon: 'fa-comment', slug: '2/general-discussion', …}1: {link: '', class: 'col-lg-4 col-md-6 col-xs-12', icon: 'fa-github', description: 'Stay tuned here to hear more about new releases and features of NodeBB!', order: 3, …}2: {cid: 7, name: 'NodeBB Plugins', description: 'Discussion regarding NodeBB Plugin development.', icon: 'fa-wrench', slug: '7/nodebb-plugins', …}3: {link: '', class: 'col-lg-4 col-md-6 col-xs-12', icon: 'fa-paint-brush', description: 'A public listing of community themes created by the NodeBB community.', order: 5, …}4: {cid: 16, name: 'Technical Support', description: 'Need help with installing or configuring NodeBB? Look here.', icon: 'fa-exclamation-triangle', bgColor: '#A1B56C', …}5: {link: '', class: 'col-lg-4 col-md-6 col-xs-12', icon: 'fa-fire', disabled: 0, description: 'Test NodeBB here! Topics and posts will be cleared on a regular basis.', …}6: {cid: 14, name: 'Area51', description: 'Development category', icon: 'fa-bomb', bgColor: '#fff176', …}length: 7[[Prototype]]: Array(0) $.get('/api/categories').then(d => console.log(d.categories[5].name)); {state: ƒ, always: ƒ, catch: ƒ, pipe: ƒ, then: ƒ, …} VM482:1 Testing Ground
But this fails
$(document).ready(function(){ $.getJSON("api/categories", function(result){ $.each(result, function(i, field){ console.log(field[i].name); }); }); });
Uncaught TypeError: Cannot read properties of undefined (reading 'name') at String.<anonymous> ((index):4337:30) at Function.each (nodebb.min.js?v=ot2kkbojvoo:64:2883) at Object.success ((index):4336:9) at I (nodebb.min.js?v=ot2kkbojvoo:64:29412) at Object.fireWith [as resolveWith] (nodebb.min.js?v=ot2kkbojvoo:64:30189) at Re (nodebb.min.js?v=ot2kkbojvoo:67:5953) at XMLHttpRequest.<anonymous> (nodebb.min.js?v=ot2kkbojvoo:67:8430) (
Even with
field.name
instead, I getundefined
in the console.. -
Ok, needed to get my head around the structure of the
JSON
array. This works fine$(document).ready(function(){ $.getJSON( '/api/categories', function(data, status) { $.each(data.categories, function (key, value) { console.log("Category name = " + this.name); console.log("Category slug = " + this.slug); }); }); });
(index):4337 Category name = Announcements (index):4338 Category slug = 1/announcements (index):4337 Category name = Blog (index):4338 Category slug = 3/blog (index):4337 Category name = Bugs (index):4338 Category slug = 20/bugs (index):4337 Category name = Chitchat (index):4338 Category slug = 19/chitchat (index):4337 Category name = Configure (index):4338 Category slug = 5/configure (index):4337 Category name = Debate (index):4338 Category slug = 28/debate (index):4337 Category name = General (index):4338 Category slug = 2/general (index):4337 Category name = Hosting (index):4338 Category slug = 18/hosting (index):4337 Category name = Mentoring (index):4338 Category slug = 8/mentoring (index):4337 Category name = Operating Systems (index):4338 Category slug = 16/operating-systems (index):4337 Category name = Resources (index):4338 Category slug = 25/resources (index):4337 Category name = Security (index):4338 Category slug = 11/security (index):4337 Category name = Test (index):4338 Category slug = 23/test (index):4337 Category name = Tips (index):4338 Category slug = 27/tips (index):4337 Category name = WordPress (index):4338 Category slug = 17/wordpress
-
-
@baris coming back here with a question - the above code I provided works fine, but of course, this doesn't fetch children. I see them listed in the JSON array returned, but is there a more efficient way of obtaining these without having to query each category being returned in the loop I have ?
-
@baris Yes, I'm doing that, but this is the result
Category name = Announcements | URL = 1/announcements | Children = (index):4346 Category name = Blog | URL = 3/blog | Children = (index):4346 Category name = Bugs | URL = 20/bugs | Children = (index):4346 Category name = Chitchat | URL = 19/chitchat | Children = (index):4346 Category name = Configure | URL = 5/configure | Children = [object Object],[object Object],[object Object],[object Object] (index):4346 Category name = Debate | URL = 28/debate | Children = (index):4346 Category name = General | URL = 2/general | Children = (index):4346 Category name = Hosting | URL = 18/hosting | Children = (index):4346 Category name = Mentoring | URL = 8/mentoring | Children = [object Object],[object Object] (index):4346 Category name = Operating Systems | URL = 16/operating-systems | Children = [object Object],[object Object] (index):4346 Category name = Resources | URL = 25/resources | Children = [object Object] (index):4346 Category name = Security | URL = 11/security | Children = [object Object],[object Object],[object Object] (index):4346 Category name = Test | URL = 23/test | Children = (index):4346 Category name = Tips | URL = 27/tips | Children = (index):4346 Category name = WordPress | URL = 17/wordpress | Children =
[object Object]
is clearly an array, but I can't find any decent way of walking it$(document).ready(function() { //var categorylist = ""; $.getJSON('/api/categories', function(data, status) { $.each(data.categories, function(key, value) { console.log("Category name = " + this.name + " | URL = " + this.slug + " | Children = " + this.children); var categorylist = $(" \ <li><a class='dropdown-item rounded-1' href='/category/" + this.slug + "'>" + this.name + "</a></li> \ "); $("#thecategories").append(categorylist); }); }); });
-
@baris said in API call or JS function to get a list of categories and URL's:
this.children.forEach(child => console.log(child))
This is odd..
$(document).ready(function() { //var categorylist = ""; $.getJSON('/api/categories', function(data, status) { $.each(data.categories, function(key, value) { //console.log("Category name = " + this.name + " | URL = " + this.slug + " | Children = " + this.children.forEach(child => child)); var categorylist = $(" \ <li><a class='dropdown-item rounded-1' href='/category/" + this.slug + "'>" + this.name + "</a></li> \ <ul> \ <li><a class='dropdown-item rounded-1' href='/category/" + this.children.forEach(child => (child.slug)) + "'>" + this.children.forEach(child => (child.name)) + "</a></li> \ </ul> \ "); $("#thecategories").append(categorylist); }); }); });
If I use
console.log
thenconsole.log(child.slug))
works, but the value isn't being collected to build theli
itemsConsole Log
6/customisation 24/guides 9/networks 10/performance 22/labs 21/learning 7/linux 15/windows 26/development 12/malware 3/privacy 14/vulnerability
-
You want to output one
li
item for each child so you need to move the loop outside. Something like thisvar categorylist = $(" \ <li><a class='dropdown-item rounded-1' href='/category/" + this.slug + "'>" + this.name + "</a></li> \ <ul>" + this.children.map(c => `<li><a class='dropdown-item rounded-1' href='/category/" + ${c.slug} + "'>" + ${c.name}) + "</a></li>`) + "</ul>" );
So for each
child
category in the children array it will create ali
element -
@baris sorted - thanks
$(document).ready(function() { //var categorylist = ""; $.getJSON('/api/categories', function(data, status) { $.each(data.categories, function(key, value) { //console.log("Category name = " + this.name + " | URL = " + this.slug + " | Children = " + this.children.forEach(child => child)); var categorylist = $(" \ <li><a class='dropdown-item rounded-1' href='/category/" + this.slug + "'>" + this.name + "</a></li> \ <ul>" + this.children.map(c => `<li><a class='dropdown-item rounded-1' href='/category/${c.slug}'>${c.name}</a></li>`).join(" ") + "</ul>" ); $("#thecategories").append(categorylist); }); }); });
Added
join(" ");
to strip the commas from the array -
More complete code, prettified...
$(document).ready(function() { //var categorylist = ""; $.getJSON('/api/categories', function(data, status) { $.each(data.categories, function(key, value) { var categorylist = $(" \ <li><span class='category-menu'><i class='fal " + this.icon + "'></i><a style='display: inherit;' class='dropdown-item rounded-1' href='/category/" + this.slug + "'>" + this.name + "</a></span></li> \ <ul style='list-style: none;'>" + this.children.map(c => `<li><span class='category-menu'><i class='fal ${c.icon}'></i><a class='dropdown-item rounded-1' style='display: inherit;' href='/category/${c.slug}'>${c.name}</a></span></li>`).join(" ") + "</ul><li class='dropdown-divider'></li>" ); $("#thecategories").append(categorylist); }); }); });
Looks like this
-
@baris one thing that puzzles me is that whilst the newly created menu is dynamically built, and displays fine on desktop, it doesn't show on mobile - apart from the one
li
I added in the navigation pane, which I am using with an id to bind the dynamically built lines.Any thoughts ?
Thanks
-
Generally having more than one element with the same id is not advisable and you should use a class instead.
-
@PitaJ Agree, although in this instance, I'm able to fire one or the other dependant on viewport
$(document).ready(function() { //var categorylist = ""; $.getJSON('/api/categories', function(data, status) { $.each(data.categories, function(key, value) { var categorylist = $(" \ <li><span class='category-menu'><i class='fal " + this.icon + "'></i><a style='display: inherit;' class='dropdown-item rounded-1' href='/category/" + this.slug + "'>" + this.name + "</a></span></li> \ <ul style='list-style: none;'>" + this.children.map(c => `<li><span class='category-menu'><i class='fal ${c.icon}'></i><a class='dropdown-item rounded-1' style='display: inherit;' href='/category/${c.slug}'>${c.name}</a></span></li>`).join(" ") + "</ul><li class='dropdown-divider'></li>" ); if ($(window).width() < 767) { $(".bottombar #thecategories").append(categorylist); } else { $(".sidebar-left #thecategories").append(categorylist); } }); }); });