46

I had some scripts specific to a view. However, the script does not seem to execute when angularjs loads the view.

Index.html

<html>
  <body ng-app="adminApp">

    <div ng-view=""></div>

    <script src="bower_components/angular/angular.js"></script>
    <script src="scripts/app.js"></script>
    <script src="scripts/controllers/main.js"></script>

</body>
</html>

Main.html - loads under ng-view

hello world
  <script>

    alert('Hello, John!')

  </script>

In this example, when the page load, I see a basic hello world printed on the website. However, I do not get any pop up saying "Hello, John".

Any idea why I cannot load scripts specific to a certain view?


Extra info app.js

'use strict';

angular.module('adminApp', [])
  .config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .otherwise({
        redirectTo: '/'
      });
  });

controllers/main.js

'use strict';

angular.module('adminApp')
  .controller('MainCtrl', function ($scope) {
    $scope.awesomeThings = [
      'HTML5 Boilerplate',
      'AngularJS',
      'Karma'
    ];
  });
Karan
  • 14,824
  • 24
  • 91
  • 157

2 Answers2

63

That's the way jqLite works. If you want scripts in templates to be evaluated, include jQuery before AngularJS. If jQuery is included, the script will be evaluated. Try removing jQuery, and you see the originally observed behavior.

Updated: since some people asked for elaboration in the comments, here it is:

When a route is matched, ngView uses jqLite's (or jQuery's, if loaded) html() method to set the content of the element (the one ngView is declared on). In other words, ngView.link() does something like this:

$element.html(template)

So it boils down to how html() is implemented in jqLite and jQuery. jqLite uses the native innerHTML property, which only sets content but doesn't evaluate scripts. jQuery, on the other hand, parses out all script tags and executes them (by constructing and appending script DOM elements to the page).

Buu
  • 49,745
  • 5
  • 67
  • 85
  • Adding jquery did the job! Thanks! :) – Karan Aug 13 '13 at 22:45
  • They probably deleted it, or whatever reason I have no idea. The the point remains: if you want to execute script, include jQuery. – Buu Oct 20 '13 at 01:39
  • Do you know, why and how jqLite did that? And is there another way instead of including jQuery? – Murat Çorlu Jan 24 '14 at 15:30
  • @MuratÇorlu because that stuff makes jqLite not quite "lite", see https://github.com/angular/angular.js/issues/369 – Buu Jan 24 '14 at 17:27
  • @hitautodestruct you should post a plunkr – Buu Jan 27 '14 at 19:44
  • @Buu I'm a bit confused here, hoping you can add some clarification. For starters your plunker no longer seems to be up (if you don't plan to update, you should probably just edit it out). Also, in my project, I have no need for jQuery ... why would jQuery's inclusion have an effect on whether partials in Angular execute – Zach Lysobey Feb 28 '14 at 17:08
  • @Filipe plunkr sometimes delete my stuff, guess I should sign up. I'll remove it. For the answer, just include jQuery. – Buu Feb 28 '14 at 19:01
  • @BuuNguyen You can use [jsFiddle](http://jsfiddle.net) instead? Or there are problem to create examples with AngularJS? – Filipe Feb 28 '14 at 19:06
  • 1
    @ZachL it's a long story to fit the comment, so I've appended to the answer. Hope it helps. – Buu Feb 28 '14 at 19:37
  • very helpful; I think I'm beginning to understand. So *jqLite* is a jQuery-ish library that angular uses internally to process the html partials? And it doesn't support ` – Zach Lysobey Feb 28 '14 at 21:34
  • 3
    @ZachL jqLite is a "lite" version of jQuery, containing minimal DOM related functionalities (html() is one of them) that AngularJS needs. The AngularJS devs don't want to depend on jQuery out of the box because it's huge. The minimal nature of jqLite means if you need s/t more (like the version of html() that evaluate scripts), you have to use jQuery. During initialization, AngularJS code automatically checks if jQuery is included and uses if it is, otherwise it uses the built-in jqLite. – Buu Feb 28 '14 at 22:20
  • If I include my script that needs to work with the view, how can I trigger it when the view has loaded? I don't want to include jquery and/or fragmentate my script. – Alberto Jul 10 '14 at 14:50
1

If I include my script that needs to work with the view, how can I trigger it when the view has loaded? I don't want to include jquery and/or fragmentate my script.

To execute the <script> tag without loading jQuery, use jqLite to find the <script> tag and then eval the innerHTML.

app.controller("vm", function($scope, $element) {

  //FIND script and eval 
  var js = $element.find("script")[0].innerHTML;
  eval(js);

});

The DEMO on PLNKR

See also AngularJS Issue #369 — jqLite should create elements in same way as jQuery

georgeawg
  • 48,608
  • 13
  • 72
  • 95