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); } }); }); });
-
Ok, I've spent WAY too much time on this already, but I'm really quite happy with how this turned out
If anyone wants to know how this it put together, it's all documented here
https://sudonix.com/topic/457/create-a-dynamic-category-list