0

I have a project where a lot of the models are going to be managed by almost the same controller-code with the only exception that they are calling different services.

The way I'm handling this now is by instantiating a Crud-Controller with common code into every custom controller and then redirecting the service-call by changing the variable inside the custom controller. I.e. vm.service.get() inside the Crud-Controller changes by setting vm.service = teamService; in a custom controller.

This is how I instantiate the Crud-Controller into my custom controllers at the moment:

$injector.invoke(Crud, this, {$scope:$scope});

This works fine, however I don't know if this is the right way to share common controller code. Maybe it is possible to instantiate a service for this use? Because the question I have (if my way of doing it is correct), how do I access other controllers while using IIFE? Right now I am not using IIFE since I have not figured out a way to do so.

I have tried with angular.module('app').controller('Crud') but it does not work.

I.e: How do I get access to the PrimaryCtrl's edit function without using $injector or relying on the $scope inheritance? http://jsfiddle.net/tcVhN/62/

  • Please, provide the code that explains the statements, a couple of lines isn't enough. – Estus Flask Jul 14 '15 at 09:42
  • I.e: How do I get access to the PrimaryCtrl's edit function without using $injector or relying on the $scope inheritance? http://jsfiddle.net/tcVhN/50/ – user2624679 Jul 15 '15 at 09:25
  • your service doesn't make sense. in `fetchUsers`, for example, you are checking if `users` exists, and if it is, you are rejecting the promise with an error, which means if users was in the cache already, you aren't returning anything. – Claies Jul 15 '15 at 09:34
  • @user2624679 I see. This is the primary reason why controllerAs is there. Dismiss $scope for everything except scope $* stuff, use `this` instead and extend controllers with JS from common function or class. – Estus Flask Jul 15 '15 at 10:01
  • @Claies Sorry. I used an old link. Correct one: http://jsfiddle.net/tcVhN/62/ – user2624679 Jul 15 '15 at 14:14
  • @estus So sorry. I used an old link. Correct one: http://jsfiddle.net/tcVhN/62/ – user2624679 Jul 15 '15 at 14:14

1 Answers1

0

It looks like your example uses Angular 1.0.x that supports global controllers out of the box. That's how it would be done with more recent Angular, without going too deep into the perils of JS inheritance.

'use strict';

(function (root, angular) {
    root.ctrls = root.ctrls || {};

    var primaryCtrl = function ($scope) {
        var self = this;
        console.log('primaryCtrl constructor', self, $scope);
    };
    primaryCtrl.prototype = {
        items: ['Item 1', 'Item 2'],
        edit: function (item) {
            //do stuff
        }
    };
    primaryCtrl.$inject = ['$scope'];

    root.ctrls.primaryCtrl = primaryCtrl;
})(this, angular);

(function (root, angular) {
    root.ctrls = root.ctrls || {};

    var secondaryCtrl = function ($scope) {
        var self = this;
        console.log('secondaryCtrl constructor', self, $scope);
    };
    secondaryCtrl.prototype = angular.extend({},
        root.ctrls.primaryCtrl.prototype,
        {
            items: ['Stuff 1', 'Stuff 2']
        }
    );
    secondaryCtrl.$inject = ['$scope'];

    root.ctrls.secondaryCtrl = secondaryCtrl;
})(this, angular);

var app = angular.module('app',[]);
app.controller('PrimaryCtrl', ctrls.primaryCtrl);
app.controller('SecondaryCtrl', ctrls.secondaryCtrl);

and

<div ng-controller="PrimaryCtrl as primary">
    <p ng-repeat="item in primary.items">{{item}}</p>
</div>

<div ng-controller="SecondaryCtrl as secondary">
    <p ng-repeat="item in secondary.items">{{item}}</p>
</div>

You may also check Angular Classy, which brings opinionated but viable extending syntax to Angular.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Thanks for your answer. How would I be able to access the primary controller if the controllers are separated in different files with IIFE? – user2624679 Jul 15 '15 at 19:54
  • Your best bet is to `require` it with build system of your choice or es6 modules. Otherwise you will have to export globals from IIFE to `window` like it is usually done, `(function (root) { var ctrl = ...; root.ctrl = ctrl; })(this);`. Keep in mind that you can always separate common methods into service and mixin them in controllers like `angular.extend(this, baseCtrlService)`, but managing dependencies by means of Angular in a big app like that will make the one shoot into his foot most times. – Estus Flask Jul 15 '15 at 21:50
  • Thanks again. So how would you solve this "problem" where you have a lot of common controller code that you want to share? Would you say that DRY is mandatory here or could you just have 3-5 very similar controllers? – user2624679 Jul 16 '15 at 08:25
  • I guess you're already following 'thin controllers, fat services' principle, so there are no logic in controllers, only scope bindings. It depends on the amount of WET code, I would personally leave them as is or go ES6/TS classes for long-term project. – Estus Flask Jul 16 '15 at 12:04