1

I will try to explain this as concisely as I can.

I have an app that can't be immediately converted to a single angular app. as a result we have a number of seperate modules that are effectively individual apps at the moment and are instantiated on their own relevant pages

Lets say we have two modules A + B both using angular-ui-router to manage state and views, they both access the same rest api but they display the information very differently. However to create or edit a resource in both A + B you use the same form.

This form has a template which can be shared easily but it also has a controller which right now is A.controller('formcontroller'). What is the best way (is there even a way) for me to take that controller away from the A module and inject it into both A + B?

some pseudo code to maybe explain what I am wondering a little clearer

angular.module('A', ['ApiService', 'ui.router'])
    .config(function($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('templateA', {
                controller: 'templateACtrl'
            })
            .state('tempalteA.form', {
                controller: 'templateAFormCtrl'
            })
    })
    .controller('TemplateACtrl', function () {
    })
    .controller('TemplateAFormCtrl', function() {
    });

angular.module('B', ['ApiService', 'ui.router'])
    .config(function($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('templateB', {
                controller: 'templateBCtrl'
            })
            .state('tempalteB.form', {
                controller: 'templateBFormCtrl'
            })
    })
    .controller('TemplateBCtrl', function () {
    })
    .controller('TemplateBFormCtrl', function() {
    });

I want to get rid of TemplateAFormCtrl and TemplateBFormCtrl and consolodate them into just FormCtrl that can be used by ui-router in both modules

Mark
  • 3,137
  • 4
  • 39
  • 76

1 Answers1

2

Ok, read the edited example and it can be done in a couple of ways, the best one I can think of (and I will explain why before the solution) is this:

angular.module('formModule', [])
  .service('formService', function(){
    //Everything that can be abstracted from templateAFormCtrl should be here
  });

angular.module('A', ['formModule'])
.config(function($stateProvider, $urlRouterProvider) {
    //$stateProvider config
    $stateProvider
        .state('tempalteA.form', {
            controller: 'templateAFormCtrl'
        })
})
.controller('TemplateAFormCtrl', function(formService) {
    //Assuming you're working with 'controller as' syntax, else attach to $scope
    this.formService = formService;
});

angular.module('B', ['formModule'])
.config(function($stateProvider, $urlRouterProvider) {
    //$stateProvider config
    $stateProvider
        .state('tempalteB.form', {
            controller: 'TemplateBFormCtrl'
        })
})
.controller('TemplateBFormCtrl', function(formService) {
    //Assuming you're working with 'controller as' syntax, else attach to $scope
    this.formService = formService;
});

Why I would do this? Yeah, you could create a controller on the 'formModule' instead of a service, but you won't be aware of the states of 'A' and 'B' from that controller, and if you later need to react to something that is set on either module or comunicate with any component from it (specially this, since you'll need to inject that component to the 'formModule' hence creating a recursive dependency), you'll have a huge problem.

The way I would do it, allows you to expose every method you want from 'formService' to your views, and on top off that, you'll be able to add code specific to either module on it's own controller.

OLD ANSWER:

The short answer would be:

  • A factory to manage everything related to API comunications (Requesting/Persisting data to the server)
  • A service to provide a common API for your controllers, that way you can abstract the methods you want to reuse, and use them on each controller by injecting the service as a dependency.

The longer answer (and I personally recommend you read it, because it will help you a big deal) is this: AngularJS: Service vs provider vs factory

Community
  • 1
  • 1
  • Thanks I have the factory part taken care of api comms is abstracted and can be accessed from whichever module needs it. I think I also have the service part already common functionality is abstracted to a service that any module can access and therefore any controller in that module. – Mark May 22 '14 at 13:11
  • What I am trying to figure out is if there is a way to not duplicate the actual controller part ie only have one FormCtrl for every module. I will read that article in case it answers that, thanks. – Mark May 22 '14 at 13:13
  • That looks like exactly what I am looking for thanks, I will leave it unchecked for now just in case someone happens a long and sees a reason not to do it this way, in the mean time I will go about implementing this – Mark May 22 '14 at 14:30
  • Hmm so lets say I have a $scope.$watch() and it is used in both controllers there is no way to put this in the service am I right? – Mark May 22 '14 at 15:34
  • Since they are different aplications, they don't know each other's state, so the service won't know if the watched value changed or not. What you can do is attach the $watch to the controller and call a function inside the service, so you would just have: `$scope.$watch('scopeProperty',formService.doSomething)` That is, if you don't need access to the controller's $scope – Hernán Magrini May 22 '14 at 15:45