3

How can I specify that a controller should be a child of another controller in the JavaScript rather than the HTML?

For example, on pageCtrl, I have a method called modalBlog that opens a blog post in a modal (Angular-UI.) I would like to specify the controller to be BlogCtrl, the same as I'm using on the actual blog page. I'd like to pass it input though (i.e. the blog post ID.) Is there a way to do something like:

$scope.modalBlog = function(postId) {
   var modalInstance = $modal.open({
   templateUrl: '...',
   controller: function(..) {
       // Set some variables
       // ...

       // set BlogController as a child controller to this
   }
};

Right now, by setting controller: 'BlogCtrl', it's parent is the route scope (from ui.router's $state), or visually:

So, the hierarchy is:

+-Root
|---- PageCtrl
|---- BlogCtrl

But when I specify an anonymous function, I get:

+-Root
|--+- PageCtrl
   +--+- <Anonymous function>

Is there a way (in just JavaScript) to achieve this hierarchy?

+-Root
|--+- PageCtrl
   +--+- <Anonymous function>
      +--+- BlogCtrl

The motivation is to re-use the code in the BlogCtrl to download the post.

I suppose completely alternative methods to achieve the same functional/end-of-the-day goals would be to:

  • create a BlogService which both this anonymous function and the BlogCtrl could use,
  • or even load a view that has a tag that specifies the BlogCtrl as a controller

And while I think these would be better methods in this particular case, I'm curious if there is a way to specify the hierarchical structure of scopes in AngularJS via JavaScript (as opposed to setting it in the HTML which is rather straight forward.)

Update:

I think the second option I gave is best (I had only thought of it while writing this question) way to implement the functionality I required.

So, my function is:

$scope.modalBlog = function(postId) {
  var modalInstance = $modal.open({
  templateUrl: '...',
  controller: function(..) {
      // Set some variables and functions
  }

};

And instead of pointing at views/blog.html, I point to views/blog-modal.html, whose top tag is:

<section ng-controller="BlogCtrl">

Which gives me the designed structure, where the controller function above is the parent of BlogCtrl.

This leads to the view being somewhat duplicated, as I'm not sure how to conditionally set the controller (e.g. ng-controller="modal?BlogCtrl:not BlogCtrl"), but it's not too bad. I'd still be curious on how to set the structure in purely Javascript though.

Graham
  • 7,431
  • 18
  • 59
  • 84
Matt
  • 1,928
  • 24
  • 44
  • I'm sorry, but I don't understand what question you're trying to ask or what problem your having. – JeffryHouser Jun 28 '14 at 15:30
  • Even I don't get it. I hope you already know if you are working with 'angular modal' then same controller can't be used for further data manipulation. you have to use new controller. still can help you if you clarify something more... – micronyks Jun 28 '14 at 15:51
  • check this approach for combining modal in your project: http://stackoverflow.com/questions/16265844/invoking-modal-window-in-angularjs-bootstrap-ui-using-javascript/23958996#23958996 – Jossef Harush Kadouri Jun 28 '14 at 16:15
  • @JeffryHouser. I tried to clear up the question a bit. Thanks! – Matt Jun 29 '14 at 16:11
  • @micronyks: I'm not sure what you mean when you say that this controller can't be used to manipulate data? Thanks! – Matt Jun 29 '14 at 16:12
  • Why don't you put your code (1st option) in Factory? so, both controllers can use it. – micronyks Jun 30 '14 at 05:21
  • @micronyks I think that'd be great, I was just curious if setting the structure in the code was possible. But yeah, if I were to restart, it would totally be in a factory. After days of thinking about it, I'm pretty sure using the other ways around produce superior code anyways, so maybe it wouldn't ever be needed anyways. Thanks! – Matt Jul 01 '14 at 15:13

1 Answers1

0

From what I understand, what you are trying to achieve is to be able to call the anonymous function defined in parent controller with modal (child) state.

Define the anonymous function(s) without accessing the scope. Then instead of passing the controller to the modal, pass the anonymous function(s).

In the parent controller:

$scope.getpost= function (postId) {
  ...
};

Modal:

$scope.modalBlog = function (postId) {
    var modalWindow = $modal.open({
        templateUrl: 'views/blog.html',
        controller: 'editBlogController',
        resolve: {
            textid: function () { return postId; },
            gettextfn: function () { return $scope.getpost; }
        }
    });
};

You should be able to pass as many reusable functions as needed by the modal controller.

If you are trying to reuse a view as well, it is not clear to me what are the conditions for such a reuse.

James
  • 376
  • 1
  • 4
  • 15
  • I never thought of using `resolve` to pass in data. (I'm still new'ish to Angular.) That's a really good idea. Thanks! – Matt Jul 02 '14 at 16:32