1

I'm trying to set up some nested views in angularjs. I've been using the ui-router library to do this which works great for the most part. The problem is that there is a separate controller for each view with no real inheritance going on between them. If I want to modify something in a parent controller from a child controller I have to use $scope.$parent . This is a bit of a pain and it can become worse if there are multiple levels of inheritance and you have to remember which level the variable you are accessing is on. Also if you forget to use $parent in your child controller and you try to modify one of the parent's variables, Angular will create a new instance of the variable which could lead to some hard to track down bugs.

Ideally I would just be able to use prototype inheritance. This would also map nicely into classes in Typescript or Coffeescript. One way I thought of to do this would be to get rid of all the parent controllers and just have the child controllers which would inherit any common functionality from prototypes (super classes). Then you would just have to throw the controller up on the $rootScope so that the parent views could access it.

Can anyone think of any issues with this solution or better solutions? Would I be better off just using $parent and letting Angular handel the "inheritance".

Thanks

2 Answers 2

1

You should be able to enable protypal inheritance if you modify the source slightly.

Open the file ./ui-router/src/viewDirective.js and you should find this near the top:

var directive = {
    restrict: 'ECA',
    terminal: true,
    transclude: true,
    ...

Add another line such that it reads:

var directive = {
    restrict: 'ECA',
    terminal: true,
    transclude: true,
    scope: true,
    ...

This should enable inheritance. I can't find a good direct source on this, but this you tube playlist is full of all sorts of angular goodness.

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

3 Comments

This worked although it does not work very well the the "controller as" syntax. for example if in my module configuration I have 'controller: "myChildCtrl as ctrl"' then I can't access the parent scope through 'this'. e.g. this would not work 'this.someParentVariable = 3'. However this would work '$scope.ctrl.someParentVariable = 3'.
There's some confusion as to how the inheritance works. $scopes are objects used by controllers and these inherit from eachother -- not the controller. When a controller is placed on a DOM element, the $scope on that element generally inherits from the $scopes on ancestor DOM elements and the controllers don't have anything to do with this directly. As far as I can tell, using the "controller as ctrl" syntax actually puts a reference to the controller on the current scope. This is the same object that you would reference inside of the controller's constructor function as "this".
"controller as" syntax is considered harmful by some (me included). You can do prototypal inheritance as mentioned above if you want to controller instances to have common functionality or instance variables, but two instances will still not share the same scope. You should use a service to share data between controllers instances.
0

As John pointed out the $scope objects inherit from each other but the actual controllers do not. So I decided to set it up so that the controllers do inherit from each other. To do this I have one root controller that just looks like this:

function rootCtrl($scope) {
    $scope.ctrl={};
    $scope.ctrl.scope = $scope;
}

Then in my most deeply nested child controllers I have something like this

function myCtrl($scope, $dependency1, $dependency2) {
    myCtrlImpl.apply($scope.ctrl, [$http, $dependency1, $dependency2]);
}

function myCtrlImpl($dependency1, $dependency2) {
    this.someVariableThatIsAccessableEverywhere = ":)";

    //If I want to access scope from here I can just do something like
    //this.scope.$watch...
}

Now if I want to move any functionality from myCtrlImpl into a base prototype, I can just use standard prototype inheritance.

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.