0

I want to have element where i can have 2 views using their own controller but only one at a time. I can't use a ng-view and use the routeProvider because in the future I need to include more ng-includes that need to change their content depending on the possible actions.

I created a fiddle http://jsfiddle.net/EvHyT/29/.

So I used a ng-include and then I set the src for it from a main controller. At that point I want to use controller 1 or controller 2.

function MainCtrl($rootScope, $scope, navService){
$scope.template = {};

$scope.loadCtrl1=function(param){
    navService.loadCtrl1(param);
}

$scope.loadCtrl2=function(param){
    navService.loadCtrl2(param);
}

$rootScope.$on('loadCtrl1', function(e, args){
    $scope.template = {'url': 'temp1'};
});

$rootScope.$on('loadCtrl2', function(e, args){
     $scope.template = {'url': 'temp2'};       
});
}

I use a service for communication because i want to move the load controller functions in a child controller.

var myApp = angular.module('myApp',[]);


myApp.factory('navService', function($rootScope) {
return {
     loadCtrl1:function(param){
        $rootScope.$broadcast('loadCtrl1', {'id':param});   
    },

    loadCtrl2:function(param){
        $rootScope.$broadcast('loadCtrl2', {'id':param});
    }
};
});

I know this solution is bad because the controllers are not yet created when a different template is inserted so my event listener will not fire. Also can I destroy the previous instances of the controller because switching between the two controllers makes my event fire multiple times.

function Child1Ctrl($scope, $rootScope){
 $rootScope.$on('loadCtrl1', function(e, args){
   alert(args.id);
});
}

function Child2Ctrl($scope, $rootScope){

$rootScope.$on('loadCtrl2', function(e, args){
      alert(args.id);
});
}
1
  • not sure i got u but did u mean something like <div ng-include="'View.html'" ng-controller="VODDataBindController" ng-controller="VODUserEventsController"></div>? Commented Aug 7, 2013 at 12:59

1 Answer 1

2

You don't need to broadcast (and shouldn't be broadcasting) to make this happen. In my experience, if you're broadcasting on the rootScope, you're probably working too hard.

A simpler way of loading the template is very similar to what you're doing:

my.NavService = function() {
  this.template = 'index.html';
  this.param = null;
};
my.NavService.prototype.setTemplate(t, p) {
  this.template = t;
  this.param = p;
};

my.ctrl = function($scope, nav) {
   $scope.nav = nav;
   $scope.load = function(t, p) {
     nav.setTemplate(t, p);
   };
};

my.ctrl1 = function($scope, nav) {
  $scope.param = nav.param;
};

my.ctrl2 = function($scope, nav) {
  $scope.param = nav.param;
};

module.
  service('nav', my.NavService).
  controller('mainCtrl', my.ctrl).
  controller('ctrl1', my.ctrl1).
  controller('ctrl2', my.ctrl2);
<script type="text/ng-template" id="temp1.html">
  <div ng-controller="ctrl1">Foo {{param}}.</div>
</script>
<script type="text/ng-template" id="temp2.html">
  <div ng-controller="ctrl2">Bar {{param}}.</div>
</script>

<div ng-controller="mainCtrl">
  <a ng-click="load('temp1.html', 16)">Load 1</a>
  <a ng-click="load('temp2.html', 32)">Load 2</a>
  <div ng-include src="nav.template"></div>
</div>

A setup like this would work much better for you.

Alternatively, you should look into selectively showing elements with ng-switch. Unlike ng-show/hide, ng-switch does not simply add "display:none" to the CSS. It removes it from the DOM.

Some notes:

  • The above example may not be a working example, it's a demonstration of the idea. A working example can be seen here: http://jsbin.com/ofakes/1 It modifies your original code.
  • JSFiddle had some issues with loading the include from the on page script tag.
  • JSBin was a little better.
  • I didn't really get it to work as expected until I broke out the templates into their own files.
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for the response but I have an issue with this solution so far. I need the controller for one object for example task. When I click load Ctrl2(2) I would like for controller 2 to get data for task with the id = 2.It works fine the first time you click it, but if I had 10 links with loadCtrl2 but different ids it doesn't work anymore so I would have to make an init function in Ctrl2 and link it somehow?
@user1138786 I'm not quite following your predicament. If you could make a jsbin with an example, I would be more than happy to comment.
Here is a jsbin jsbin.com/ewoyoq/3. What I want to achieve is to have the red zone using the same template and do the same stuff for either an item for Category 1 or Category 2(but it needs an id and a parameter to know if it's for category 1 or 2). The green zone should have 2 types of templates and use different controllers. I can't figure the best approach for this case.
@user1138786 Hmm, I don't quite understand completely, so I'll offer at least some advice: What I've demonstrated for you with the "navService" is nothing special. It's a basic dependency injected state model. In general, to accomplish what you're wanting in Angular, you need to have one of these models that you manipulate and your layout should check the values in it and update accordingly. In your case, you'll need a little more logic around the includes and values, but you can do it and the same principles apply.
@user1138786 It sounds like you don't actually want to use ng-include for the red box, only for the green.

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.