Creating a dynamic dropdown menu using AngularJS and Bootstrap

I'm currently developing a module that will dynamically generate a menu. I am looking for guidance on how to execute a directive after adding new <li> elements with the css class dropdown, which is also added through ng-class.
Here is the code snippet:

angular.module('myapp', ['ui.bootstrap'])
.factory("menuService", ["$rootScope", function($rootScope) {
    "use strict";

    return { 
        menu: function() {
            $rootScope.globalMenu;
        },    
        setMenu: function(menu) {
            $rootScope.globalMenu = menu;
        }
    };

}])
.controller("MainController", ["$scope", "menuService",
    function($scope, menuService){

        menuService.setMenu([{href:"#", label:"Dropdown",
                                dropdown:[{href:"/edit", label:"Edit"}]},
                             {href:'/', label:'test'}]);

        $scope.bodyText = "Some text";


    }]);

This HTML code snippet is as follows:

    <ul class="navbar-nav nav navbar-left">
        <li ng-repeat="menu_element in globalMenu" ng-class="{dropdown: menu_element.dropdown != undefined}">
            <a ng-href="{{menu_element.href}}" ng-class="{'dropdown-toggle': menu_element.dropdown != undefined}">
                {{menu_element.label}}
                <b class="caret" ng-if="menu_element.dropdown != undefined"></b>
            </a>
            <ul ng-if="menu_element.dropdown != undefined" class="dropdown-menu">
                <li ng-repeat="sub_element in $parent.menu_element.dropdown">
                    <a ng-href="{{sub_element.href}}">{{sub_element.label}}</a>
                </li>
            </ul>
        </li>
    </ul>

To view the code snippet in action, visit this link: http://plnkr.co/edit/pgH35mmsjLJqV4yJuSYq?p=preview

My goal is to achieve functionality similar to running $("li.dropdown").dropdown() in jQuery after adding all the ul>li blocks dynamically. Since I am new to AngularJS, I am seeking advice on how to accomplish this in an angular way.

I have researched directives and their usage, but I have not been able to determine how to apply a directive at runtime. While exploring the transclude: element feature in a directive like ui.bootstrap.dropdownToggle, it does not seem to be what I need. I am confident there is a straightforward solution out there, but I have yet to discover it on my own...

Answer №1

We've cracked it!

After some trial and error, I managed to figure it out using a combination of ng-if and ng-repeat-start. Helpful insights from the comments revealed that ng-class doesn't execute directives.

    <ul class="navbar-nav nav navbar-left">
        <span ng-repeat-start="menu_element in globalMenu"></span>
        <li ng-if="menu_element.dropdown !== undefined">
            <a ng-href="{{menu_element.href}}" class="dropdown-toggle">
                {{menu_element.label}}
                <b class="caret" ></b>
            </a>
            <ul class="dropdown-menu">
                <li ng-repeat="sub_element in $parent.menu_element.dropdown">
                    <a ng-href="{{sub_element.href}}">{{sub_element.label}}</a>
                </li>
            </ul>
        </li>
        <li ng-if="menu_element.dropdown === undefined">
            <a ng-href="{{menu_element.href}}">
                {{menu_element.label}}
            </a>
        </li>
        <span ng-repeat-end></span>
    </ul>

You can see a functional demo on Plnkr. There seems to be an issue with the css on Plunker, but it was working fine yesterday... nevertheless, everything is still functioning as intended.

Answer №2

Thank you for this helpful information. I have implemented a slight variation on the theme.

<ul class="nav navbar-nav">
  <li ng-repeat='link in menu track by $index' ng-class='[{dropdown:link.sub}]'>
    /* regular menu */
    <a ng-if='!link.sub' ng-bind='link.id' ng-click='jump(link.to)'></a>
    /* dropdown menu */
    <a ng-if='link.sub' class="dropdown-toggle" data-toggle="dropdown">
      <span ng-bind='link.id'></span>
      <ul class="dropdown-menu inverse-dropdown">
        /* repeat for submenu */
        <li ng-repeat='slink in link.menu track by $index'>
          <a ng-bind='slink.id' ng-click='jump(slink.to)'></a>
        </li>
      </ul>
    </a>
  </li>
</ul>

In my menu array, each element is of the form

{id:'name', to:n}

where n refers to an array containing HTML content that I insert into the page. For submenus, the menu array element looks like this:

{id:'name', sub:true, menu:[{id:'name', to:n}, etc.]}

I attempted using ui-bootstrap but found it challenging to grasp.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

While Ajax POST is functional on desktop, it does not seem to work on Phonegap applications or Android

I am facing an issue with a global function that does not seem to work properly in the PhoneGap Desktop app or Chrome Mobile on Android. Surprisingly, it works perfectly fine only in the Chrome PC version. The function is called using an onClick event, a ...

HTML two-row horizontal list with truncation

My dilemma involves a horizontal list of items that expand the full width of their container and wrap onto the next line. However, I only want to show two lines of items initially, with a "show more" link to reveal additional rows in increments of two unti ...

An issue encountered in the axios package of vue.js, specifically with the error message "id=[object%20Object]"

I am facing an issue where I have an id called "test" as a parameter and I pass it to the index.js store. The error I see in the console is users?id=[object%20Object]. I tried converting the id with this.id.toString(), but unfortunately, it did not resolve ...

The function 'ChartModule' cannot be called, as function calls are not supported

I am encountering a similar problem as discussed in Angular 2 - AOT - Calling function 'ChartModule', function calls not supported ERROR: Error encountered while resolving symbol values statically. Trying to call function 'ChartModule&apos ...

Do these exports serve the same purpose?

Can someone help me understand why one export works while the other doesn't? I've tried to figure it out on my own but I'm stuck. Functioning Example const dataStore = new Vapi({ baseURL: 'http://domain.test/api', state: ...

What is the best way to transmit two variables in a single message with Socket.io?

My goal is to send both the clientid and username through the socket communication. client.userid = userid; client.username = username; client.emit('onconnected', { id: client.userid, name: client.username }); I attempted this approach, how ...

Angular View receives OAuth Token Response via Cookie

I've been tackling this issue for a couple of hours now and could really use some assistance. I created a basic app that displays a "Login Using Google" button in an Angular view, which then redirects the user to the Google OAuth page. Below is the co ...

Tips for performing intricate sorting within a jQuery tableSorter

I am facing an issue with my table data structure. Cell1 Cell2 Computers 10 Dell 5 IBM 3 Compaq 2 HDDs 12 Seagate 7 Samsung 3 Test 2 Monitors 18 Seagate 7 Samsung 9 D ...

What is the best way to set conditions for document side script?

I'm struggling to disable the horizontal scroll when the viewport width is 480px or less. The script that controls the scroll behavior on my website looks like this: <script> $(function () { $("#wrapper").wrapInner("< ...

The functionality of ui-router appears to be limited when accessed from a nodejs directory, however, it functions properly on

It's strange that ui-router is not functioning as expected on my computer. The setup involves an index.html file serving as a header and test.html as an attached view. Interestingly, it works perfectly fine on Plunker. The content of index.html match ...

Utilize JavaScript API for generating and retrieving XSD schema and XML documents

Are there any stable JavaScript APIs that can be used to generate and read XSD schemas and XML documents? My specific requirement is: Allow one user to define/generate an XSD schema through a UI. Later, allow another user to provide appropriate data ...

The issue with SendKeys in Selenium is that it is only inputting a portion of the string, rather than the entire string

Recently, I have encountered an issue with my code while trying to log in to a webpage using the sendKeys method for entering the username and password. The method seems to be only inputting a few select letters from the entire username. This problem has s ...

AngularJS directive generates observers

I developed an angular directive that generates a numeric spinner (<input type="number>) where users can input minimum and maximum values. However, I've noticed that Angular sets up watches for the min and max values passed to the directive, as ...

"Troubleshooting the slow loading of PDF files when using React's render-pdf feature

After creating a table with the ability for each row to generate and download a PDF using render-pdf npm, I encountered an issue. When the user clicks the download button, the PDF preview opens on a new page. However, there are problems with rendering as a ...

Create a prototype class in NuxtJS Vue

What is the correct way to set a class to prototype in Vue NuxtJS? I have created a plugin Here is my nuxt.config.js file: plugins: [ { src: "~/plugins/global.js" }, ], The global.js file contains: import Vue from "vue"; import CustomStore from "dev ...

Error encountered in Firefox with Protractor test (id not found), yet successful in Internet Explorer and Chrome

My Protractor test is successfully running against IE and Chrome, but when I run it against Firefox, it returns an error saying it cannot find the element on the page - any suggestions? The HTML structure is as follows - it provides options when the custo ...

What is the method to utilize attributes from one schema/class in a separate schema?

Consider the scenario presented below: Base.ts import Realm from 'realm'; export type BaseId = Realm.BSON.ObjectId; export interface BaseEntity { id?: BaseId; createdAt: string; updatedAt: string; syncDetails: SyncDetails; } e ...

What could be causing the page to refresh every time a post or update is made using a mock REST API with JSON

I have been using Json-Server to mock API requests, but I'm facing an issue where the page reloads every time I fetch or update a post. I've tried searching for a solution, but haven't found one yet. Interestingly, even though I followed a ...

Utilize underscore's groupBy function to categorize and organize server data

I am currently utilizing Angular.js in conjunction with Underscore.js This is how my controller is structured: var facultyControllers = angular.module('facultyControllers', []); facultyControllers.controller('FacultyListCtrl', [' ...

Transforming HTML with JavaScript

I am facing a challenge in my JavaScript application where I receive HTML code from an endpoint that contains radio buttons. Unfortunately, I cannot modify the HTML content coming from this endpoint. My goal is to convert these radio buttons into regular b ...