Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

We've got an existing application where the client-side is jQuery / Bootstrap. It consists of many tabs where each tab is defined in a module imported via. require.js. The tab javascript is handed a parent DOM element and is in charge of drawing itself inside of that element.

We'd like to start building new functionality (tabs) in AngularJS and running into some problems doing that.

My thinking is that we could tag the body with ng-app and in the main page code conjur up an app module window.app = angular.module('ourApp', []); and later, as tabs are loaded, create and wire-up the controllers.

I've built a simple single-page example that exhibits the problem we are having (below or here http://jsfiddle.net/p4v3G/1/).

The only way I've been able to get the example to work is manually calling angular.bootstrap which I'm pretty sure is wrong. Also, that only works the first time so if I click the button twice (equivalent to navigating to the tab, away from it, and back again within our app), Angular isn't wired up properly.

I'd appreciate any help.

<body ng-app='testApp'>
    <div id="main" style="border: 1px solid #000; background: #ffdddd;">Click button to replace template and wire up controller...</div>
    <button id="button1">Load</button>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min.js"></script>
    <script>
        var app = angular.module('testApp', []);
        jQuery(function() {
            $("button").click(function() {
                // controllers are wired up in click handler to simulate environment where we
                // are looking to embed angular inside of an existing bootstrap/jquery application 
                // where new tabs (loaded as separate modules through require) are loaded on-demand.
                app.controller('TestController', function($scope) {
                    $scope.message = 'Hello World, from Controller #1';
                });

                $("#main").html('<div ng-controller="TestController">{{message}}</div>');

                // Bootstrap works the first click but not subsequent clicks
                angular.bootstrap(document, ['testApp']);
            });
        });
    </script>
</body>
share|improve this question
    
What do you want to do? be specific. I'll try to help you. – micronyks Jul 8 '14 at 17:29
    
Thank you. When a user selects a tab/view in our existing application it pulls in a javascript module (requirejs) and gives it an element (a piece of the page) in which to draw itself. I'd like to start using Angular for some of these but, to work in the existing app, that requires me to setup/teardown Angular applications at runtime. So when a new tab is loaded we'd push the ng-marked up html into the DOM and start a new Angular app bound to that DOM element. When they leave the tab we would destroy the app. – Jeff Clement Jul 8 '14 at 19:30

To chunk up your appliation so that only the relevant parts are instantiated etc. what you need is angular ui-router. You would then set up a parent state for your tab-control with child states for each of your tabs. That way you both get deep linking and the performance you want with loading only the relevant tab.

As for requirejs, I encourage you to firstly consider if you really need it. In my opinion the javascript making up an angular application is usually much terser than a jquery application due to the declarative nature of the technology. Therefore loading all of the javascript at boot-time is ok. Your templates however may not be as simple, but by using templateUri references to templates they may be loaded as needed. (Personally I prefer compiling them to javascript and placing them in the $templateCahce at the cost of boot-time, but that's another matter.)

That being said, if my observations do not hold for your scenario/application/codebase, then others have had great success incorporating requirejs with angularjs. For a nice introductory talk on that subject see this nice ng-conf video.

Best of luck!

share|improve this answer
    
Thanks for the response. In this case we are working within an existing application and can't start adjusting the tab controller nor abandoning requirejs. The hope is that we can just make use of angular while a particular tab is visible and throw it away when the tab is closed. – Jeff Clement Jul 8 '14 at 19:06
    
Like I said, you don't have to abandon requirejs. But I do think you have to at least modify your tab-controller somewhat. I mean, you want the tab-controller to do a new thing and usually new thing means at least modify. – Mithon Jul 8 '14 at 20:45
    
Furthermore I urge you to rethink your approach. Angular (and some other frameworks) are part of a declarative paradigm which is very different from jQuery. Adopting AngularJS piecemeal sounds like a very painfull process. If I were you I'd see if the polymer project can help you with what you want here and if you're serious about Angular, do a proof of concept project and if you deem it worthwhile adopt it more fully. – Mithon Jul 8 '14 at 20:48

Could you be more precise, what type of errors appears. You don't need use jquery. Check this code and compare http://jsfiddle.net/pokaxperia/3w6pb/1/

HTML

<body ng-app='testApp'>
    <div ng-controller="TestController">    
        <span id="main" style="border: 1px solid #000; background: #ffdddd;">{{message}}</span>
        <button ng-click="loadMessage();" id="button1">Load</button>
    </div>   
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
</body>

script

var app = angular.module('testApp', []);
app.controller('TestController', ['$scope',function($scope) {
    $scope.message = "Click button to replace template and wire up controller...";
    $scope.loadMessage = function(){
        $scope.message = 'Hello World, from Controller #1';
    };
}]);

Or check your code on jsfiddle, but with few variants http://plnkr.co/edit/fUQDpO?p=preview

HTML

<body>
    <example-tabs></example-tabs>
    <div class="panel" ng-show="isSelected(1)">Panel One</div>
    <div class="panel" ng-show="isSelected(2)">Panel Two</div>
    <div class="panel" ng-show="isSelected(3)">Panel Three</div>
</body>

Main script:

var app = angular.module('tabsExample', ['tabDirectives']);

Directive to load Tabs

var app = angular.module('tabDirectives', []);
app.directive('exampleTabs', [
  function() {
    return {
      restrict: 'E',
      templateUrl: 'example-tabs.html',
      controller: function($scope) {
        $scope.tab = 1;
        $scope.selectedTab = function(setTab) {
          $scope.tab = setTab;
        };
        $scope.isSelected = function(checkTab) {
          return $scope.tab === checkTab;
        };
      }
    };
  }
]);
share|improve this answer
    
Thanks for the response. We have an existing application and we are trying to start using Angular without changing the existing application. I know how to create an Angular version of my example but, in this case, jQuery/bootstrap are in control of the tabs (that can't change) and what I would like is when the tab is selected and jQuery pushes the template into the page, to then attach an Angular app to just that component of the page while the tab is selected so that we can start implementing new components of the application in Angular. – Jeff Clement Jul 8 '14 at 19:07
    
I agree. But I think firstly, you should go through Angular-Ui and find the tabbing option using angular. I know it'd be a bit headache process to convert existing application into another one. Secondly, you can use both at a same time. I've seen your fiddle. But i can't get what you want to achieve. I've understood your concept and concern but i'm more interested in action that to be performed in your app. – micronyks Jul 9 '14 at 4:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.