4

Why does adding AngularJS to a page break it? What can I do to allow it to function correctly? Controls stop rendering. Menus stop expanding.

I am trying to divide the index.html page of an existing Bootstrap theme into partials / templates. Unfortunately, as soon as I move the HTML out of the index.html the controls on that page break.

The theme I am using is KingAdmin v1.3 from WrapBootstrap.com: https://wrapboo...

The only markup I'm adding is...

ng-app="app"

<div ng-include="'shell.html'"></div>

<script src="assets/thirdparty/angular/1.2.26/angular.js"></script>

<script src="assets/app/app.js"></script>

The shell.html contains only the portion of the body that was in the index originally...

enter image description here

WITHOUT ANGULAR:

enter image description here

WITH ANGULAR:

enter image description here

INDEX.HTML:

<head>
    <title>Dashboard | KingAdmin - Admin Dashboard</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="description" content="KingAdmin - Bootstrap Admin Dashboard Theme">
    <meta name="author" content="The Develovers">

    <!-- CSS -->
    <link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css" media="screen">
    <link href="assets/css/font-awesome.min.css" rel="stylesheet" type="text/css" media="screen">
    <link href="assets/css/main.css" rel="stylesheet" type="text/css" media="screen">

    <!--[if lte IE 9]>
            <link href="assets/css/main-ie.css" rel="stylesheet" type="text/css" media="screen" />
            <link href="assets/css/main-ie-part2.css" rel="stylesheet" type="text/css" media="screen" />
    <![endif]-->

    <!-- Fav and touch icons -->
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/ico/kingadmin-favicon144x144.png">
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="assets/ico/kingadmin-favicon114x114.png">
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="assets/ico/kingadmin-favicon72x72.png">
    <link rel="apple-touch-icon-precomposed" sizes="57x57" href="assets/ico/kingadmin-favicon57x57.png">
    <link rel="shortcut icon" href="assets/ico/favicon.png">

</head>

<body class="dashboard">

    <div ng-include="'shell.html'"></div>

    <!-- Javascript -->
    <script src="assets/js/jquery/jquery-2.1.0.min.js"></script>
    <script src="assets/js/bootstrap/bootstrap.js"></script>
    <script src="assets/js/plugins/modernizr/modernizr.js"></script>
    <script src="assets/js/plugins/bootstrap-tour/bootstrap-tour.custom.js"></script>
    <script src="assets/js/king-common.js"></script>

    <script src="assets/js/plugins/stat/jquery.easypiechart.min.js"></script>
    <script src="assets/js/plugins/raphael/raphael-2.1.0.min.js"></script>
    <script src="assets/js/plugins/stat/flot/jquery.flot.min.js"></script>
    <script src="assets/js/plugins/stat/flot/jquery.flot.resize.min.js"></script>
    <script src="assets/js/plugins/stat/flot/jquery.flot.time.min.js"></script>
    <script src="assets/js/plugins/stat/flot/jquery.flot.pie.min.js"></script>
    <script src="assets/js/plugins/stat/flot/jquery.flot.tooltip.min.js"></script>
    <script src="assets/js/plugins/jquery-sparkline/jquery.sparkline.min.js"></script>
    <script src="assets/js/plugins/datatable/jquery.dataTables.min.js"></script>
    <script src="assets/js/plugins/datatable/dataTables.bootstrap.js"></script>
    <script src="assets/js/plugins/jquery-mapael/jquery.mapael.js"></script>
    <script src="assets/js/plugins/raphael/maps/usa_states.js"></script>
    <script src="assets/js/king-chart-stat.js"></script>
    <script src="assets/js/king-table.js"></script>
    <script src="assets/js/king-components.js"></script>

    <script src="assets/thirdparty/angular/1.2.26/angular.js"></script>

    <script src="assets/app/app.js"></script>

</body>
</html>

UPDATE 2014-11-25
I've confirmed this is not me. I had a friend attempt to convert a single page in the template to Angular partials using ng-include tags and setting it up behind a proper Node.JS server. He had the same results. As soon as Angular renders the first page, tons of functionality breaks. the expand/collapse logic everywhere stops working. Most of the controls stop rendering properly.

NOTE
Someone mentioned that the problem might be caused by the use of ng-include tags and partials WITHOUT the partial file having a contoller. The side bar, top bar, breadcrumb are all being included as static HTML / Jade files via an ng-include. A route is passing in the controller for the main body, however the problems exist within this area as well.

Here is a link to the template on the developer's site:

KingAdmin Dashboard Theme

And here is how it currently looks:

enter image description here

Quick look at the modifications from the index.html page:

enter image description here

10
  • 2
    Any errors in the console? Commented Nov 12, 2014 at 0:43
  • The only error was a jquery map file. The template did not include all of the jquery files. However, I've added a folder with the upgraded jQuery, and all associated files, and the error is gone. This did not change the results above. Commented Nov 12, 2014 at 19:07
  • for the glyphicons right padding seems to be related to your html compression or template engine which removes spacing between tags. For the rest seems angular is not runing Commented Nov 25, 2014 at 22:22
  • do you have an ng-app directive somewhere in your html or do you bootstrap angular manually from your js ? Commented Nov 25, 2014 at 22:24
  • 1
    The simple answer is to switch to angular-ui.github.io/bootstrap and not use the jQuery-specific bootstrap JavaScript. Commented Dec 2, 2014 at 10:00

3 Answers 3

3
+25

PARTIALLY RESOLVED:
Not sure if this would be considered a hack. Someone with more knowledge of jQuery and Angular could / should chime in to tell you if this is safe.

STILL UNRESOLVED:
This seems to work while the page is being loaded for the first time. It does NOT work if you navigate away from the page and back again (using the back button, for example). I believe this is happening due to Angular injecting the body and NOT re-rendering the entire page... or the scripts. There's probably something that can be done within each template that uses jQuery (re-init somehow, etc.). There seem to be tons of questions / examples discussing similar problems with the DOM, jQuery, and using timeouts to correct them:

AngularJS: How can I run a directive after the dom has finished rendering?

The entire fix is in with your common resource scripts, king-common.js, etc.. They each have several rendering functions that appear to be called up front, however the DOM is still being rendered.

Example:

$(document).ready(function(){
    $('.main-menu .js-sub-menu-toggle').click( function(e){
    [snip]
    $li.find('.sub-menu').slideToggle(300);
});

By wrapping each of these operations in a setTimout you postpone rendering until after the DOM is modified:

$(document).ready(function(){
    setTimeout(function(){
        $('.main-menu .js-sub-menu-toggle').click( function(e){
        [snip]
        $li.find('.sub-menu').slideToggle(300);
    },1000);
);

These have been moved to the tail end of your scripts.jade / scripts.html file. This was done initially as an attempt to delay the firing of these methods, so this might be unnecessary. Still, that's part of how we arrived at a functioning template.

Sign up to request clarification or add additional context in comments.

1 Comment

This is a bad idea because the DOM may not be rendered 1 second after the timeout is invoked
2

Your problem is Bootstrap is not watching for the newly created elements on your page that angular compiles for you. You can create directives that can call the the Bootstrap jQuery method that add the Bootstrap bindings to your element, such as ($('.dropdown').dropdown()).

There is a wonderful AngularJS library that replaces that is an angular agnostic rewrite of bootstrap.js that may fix this for you: http://angular-ui.github.io/bootstrap/

For a quick hack, if you want all your elements with the .dropdown class to use Bootstrap dropdown, you would create a directive like this.

angular.module('app')

        // Directives: https://docs.angularjs.org/guide/directive
       .directive('dropdown', [

        // Use window dependency
        '$window',

        // Returns a directive
        function ($window) {

            return {
                // Restrict to attribute, or class name so can be used like so:
                //
                // <a class="dropdown btn btn-primary">Dropdown button</a>
                // or
                // <a dropdown class="btn btn-primary">Dropdown button</a>
                restrict: 'AC',

                link: {
                    post: [

                        // This dependency gives you the element with
                        // the directive wrapped as a jQuery object
                        '$element',

                        function ($element) {
                            $element.dropdown();
                        }
                    ]
                }
            };

        })

Comments

1

I think you should reconsider your dependencies. The elements broken in your UI seems to require jquery, for instance: jquery.easypiechart.min.js

At https://docs.angularjs.org/misc/faq you can read:

Does Angular use the jQuery library? Yes, Angular can use jQuery if it's present in your app when the application is being bootstrapped. If jQuery is not present in your script path, Angular falls back to its own implementation of the subset of jQuery that we call jQLite.

Angular 1.3 only supports jQuery 2.1 or above. jQuery 1.7 and newer might work correctly with Angular but we don't guarantee that.

Notice that angular requires jQuery 2.1 or above, whilst Bootstrap require the latest 1.1.x version of jQuery (Bootstrap does not support jQuery 2+ due to jQuery 2 does not support IE8).

After reading the above you should also read:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.