Multi level dropdown menu (Tree dropdown) with Angular 2 - javascript

Hi I was developing a multilevel tree dropdown component. But am kind of confused on how to develop the component, since the data might have so many levels and sub levels. Currently am stuck with a better approach or idea
I know how to hardcode the data and create the menu like below with pure HTML and css. How can I do with Angular with backend dynamic data? Thanks in advance.
HTML:
<ul class="top-level-menu">
<li>About</li>
<li>Services</li>
<li>
Offices
<ul class="second-level-menu">
<li>Chicago</li>
<li>Los Angeles</li>
<li>
New York
<ul class="third-level-menu">
<li>Information</li>
<li>Book a Meeting</li>
<li>Testimonials</li>
<li>Jobs</li>
</ul>
</li>
<li>Seattle</li>
</ul>
</li>
<li>Contact</li>
</ul>
Sample data:
data = [
{
id: 1,
name: 'root1',
children: [
{ id: 2, name: 'child1' },
{ id: 3, name: 'child2' }
]
},
{
id: 4,
name: 'root2',
children: [
{ id: 5, name: 'child2.1' },
{
id: 6,
name: 'child2.2',
children: [
{ id: 7, name: 'subsub' }
]
}
]
}
];

I don't think you can make your component completely dynamic in this case but you can have a array of objects in typescript which has all your options in the menu and use *ngFor to iterate.
In .ts
let menu = [{
'About': '#link'
},
{
'Services': '#link'
}, {
'offices': [{
'Chicago': '#link'
}, {
'Los Angeles': '#link'
}, {
'New York': [{
'Information': '#link'
}, {
'Book a Meeting': "#link"
}]
}]
}
]
and iterate through these nested objects in your html. If you do not have too much things to add remove frequently from your menu it's better to go with hard coding.

I don't know if you are still looking for the answer. If yes and for new viewer, then I have created a plugin for Angular which creates a Multilevel menu.
Here is a NPM Link and Github Link, the documentation is very sweet and simple.
Just in case, if you wanna see more examples, I have a demo for you and this is the Github Repo of the demo.
If something doesn't work for you, and you still wanna use this plugin, then create an issue here I'll help you out.
P.S. it works in IE11 as well.
Thanks

Related

Retreiving specific data from JSON repsonse only in certain array indexes

Hey sorry if this has been asked before, I haven't found an answer that has helped me.
I am working on building a personal application using the free Ticketmaster application but I'm having trouble with the JSON response.
An example of the response is:
data: {
classifications: [
type: {
id: 1,
name: "Dont want this"
}
],
[
type: {
id: 2,
name: "Dont want this"
}
],
[
category: {
id: 3,
name: "Food & Drink"
}
],
[
category: {
id: 4,
name: "Music"
]
}
I am trying to retrieve category names such as "Family", "Food & Drink", "Music" etc but only at some indexes does the array have category objects, the others have type.
Can someone tell me how to go through this array and only get the name when it is at category.name?
Any help is appreciated :)

ObservableArray not working as expected

I am very new to knockout.js (just picked it up yesterday), but I was suggested it for what I'm trying to do.
My dilemma is this:
i set the following "initialData" as a json array:
var initialData = [
{
id: 0,
pcName: "Test1"
},
{
id: 1,
pcName: "Test2"
},
{
id: 2,
pcName: "Test3"
},
{
id: 3,
pcName: "Test4"
},
{
id: 4,
pcName: "Test5"
}
];
followed by the following (simple) model:
var PCModel = function (pcs) {
var self = this;
self.pcsList = ko.observableArray(ko.utils.arrayMap(pcs, function (pc) {
return { id: pc.id, pcName: pc.pcName };
}));
and apply my bindings as such:
ko.applyBindings(new PCModel(initialData));
i then try to loop through my (what should be) pcsList:
<ul class="nav nav-tabs" id="sortable" data-bind="foreach: pcsList">
<li>
<a data-bind="attr: {href: '#' + id}, text: pcName"></a>
</li>
</ul>
And yet, nothing seems to happen. I cant seem to figure out why.
Please help.
For anyone that may stumble around here, my problem was simply not calling applyBindings AFTER the document was ready. wrapping it in $("document").ready(... solved the problem.

How to write this Store structure?

I'm trying to figure out the best way for my Redux Store to handle lists. Right now it looks like this:
Store = {
users: [],
posts: [],
lists: [],
}
My problem with this, is the list array. Essentially it's a store for paginated lists of a specific resource, so for example:
lists: [
{
id: 'users/43/posts',
items: [25, 36, 21]
}
]
Since I am using the url as the id, my component that shows a user's list of posts will know exactly which list to display. Now someone has told me that, this is a very very bad idea. And I just want some advice on what could be better. Another approach suggested was this:
users: [{
id: 2,
posts: [
{
url: 'users/2/posts',
items: [13, 52, 26],
}
]
}]
So what I don't understand, how does Redux know where to save this list? Do I have to specify in the action arguments where to save it?
Thank you for your advice.
Well, technically, anything works if you make it work! The second approach looks more mature, though. You don't want to use URLs as ID. IDs should be numbers or special sequence of characters+numbers. When your application grows, you'll want to normalize your data i.e. store the IDs in a separate array and transform the array of objects into an object with keys as ID.
Example from Normalizr
[{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}, {
id: 2,
title: 'Other Article',
author: {
id: 1,
name: 'Dan'
}
}]
can be normalized to -
{
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 1
},
2: {
id: 2,
title: 'Other Article',
author: 1
}
}
}
}
When your application grows, you'll have multiple reducers and sub-reducers. You'll want to slice a specific portion of your state-tree and so on. For that reason someone might have advised you to store your state in a different manner.
But again, anything works if you make it work! Good luck!

Need help in AngularJS deep filtering

So, I've been trying to filter an select with another based on this informations came from a web service:
{
sections: [
{
st_id: '1',
st_nm: 'name1',
blocks: [
{
bl_id: '1',
bl_nm: 'block1'
}
]
},
{
st_id: '2',
st_nm: 'name2',
blocks: [
{
bl_id: '2',
bl_nm: 'block2'
},
{
bl_id: '2-1',
bl_nm: 'block2-1'
}
// ... and so on
]
}
// ... and so on
]
}
I tried a lot of things and combinations, but I'm really new in Angular and nothing works. I need filter the second select, and fill with the "blocks" information, with the "st_nm" field selected in the first select element.
I'm grateful for your answers!
I think I know what you're trying to do here and here's my suggestion:
<select id="st_select" ng-model="st_selected" ng-options="sect.st_nm for sect in sections">
<select id="blocks_select" ng-model="block_selected" ng-options="block.b1_nm for block in st_selected.blocks">

Handlebars JS (or EJS) templating: Divide list into categories

I want to create an unordered list based on an array of objects using Handlebars JS.
The objects take the following form:
{ name: 'NameOne', id: 001, category: 2 }, { name: 'NameTwo', id: 002, category: 1 }, { name: 'Name Three', id: 003, category: 1 }, { name: 'Name Four', id: 004, category: 3 }...
At the moment I have a template with an each function which compiles an UL with each object making a new list item, as so:
{{#each this}}
<li>{{ name }}</li>
{{/each}}
What I would like to do is find the simplest way to divide the list depending on categories, so I could end up with something like this...
Category 1
NameTwo
NameThree
Category 2
Name One
Category 3
Name Four
If I can do this only with the template, that would be perfect, but I can also change the JS which compiles the template if needed. I would also be open for using EJS templates if that is a better solution. I have thought of a couple of solutions, but all seem very over-complicated and don't work very well, but surely this can be quite a common problem and there must be good solutions.
Many thanks.
Hi when I'm solving problems like this, I tend to manipulate the data though JavaScript to keep the template clean.
How about trying something like this:
HTML
{{#each list}}
<ul>
<li>
Category {{#key}}
<ul>
{{#each this}}
<li>{{name}}</li>
{{/each}}
</ul>
</li>
</ul>
{{/each}}
JS
var rawData = [
{ name: 'NameOne', id: 001, category: 2 },
{ name: 'NameTwo', id: 002, category: 1 },
{ name: 'Name Three', id: 003, category: 1 },
{ name: 'Name Four', id: 004, category: 3 }
];
var data = {
list:{
}
};
for (var i = 0; i < rawData.length ; i++) {
var a = rawData[i];
var cat = a.category;
if(typeof data['list'][cat] === 'undefined'){
data['list'][cat] = [];
}
data['list'][cat].push(a);
}
Also here is a jsfiddle

Categories