0

I am repeating same code for all the controllers.

E.g

$scope.CANCELLATION_IN_PROCESS = function(getOrder) {
    return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
}

We are using CANCELLATION_IN_PROCESS in dom view to show/hide a hard-coded message.

Is there any way to optimize the code.

I tried using services but I am unable to apply on view. The issue with param "getOrder" as it will only be available in the view and remain undefined in my controller with services.

Thanks MG

diiN__________
  • 7,393
  • 6
  • 42
  • 69

5 Answers5

1

This function can be attached to $rootScope:

angular.module('myModule').run(function($rootScope) {
    $rootScope.CANCELLATION_IN_PROCESS = function(getOrder) {
        return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
    }
});

and then just used in any part of your application template:

CANCELLATION_IN_PROCESS(order)
Nailgun
  • 3,999
  • 4
  • 31
  • 46
  • Bad bad solution. The scope should not contain logic. The scope should be used to just bind the view with the model whenever possible. Refer: http://stackoverflow.com/questions/32761540/why-using-rootscope-with-functions-is-not-recommended – Devesh Sati Sep 14 '16 at 07:38
  • @DeveshSati bad or good depends on the situation. This solution is the most simple one and if used wisely it works well. And the solution you provided is not much different as it uses controller scope instead of rootScope. The good practice is to work with controller itself (vm = this). – Nailgun Sep 14 '16 at 07:47
0

Move the method to base controller (create if needed), that is on the top of the app, and use controllerAs syntax. Name it like baseCtrl and use baseCtrl.CANCELLATION_IN_PROCESS in html.

Makarov Sergey
  • 932
  • 7
  • 21
0

Well if you want to reuse and abstract the logic from the controllers, the way to go is a service in my opinion. Since services are singletons, the function wouldn't be created again and again for each controller you use it in.

To use the service method in the view, you have to bind the service method with a scope method, or the ViewModel if using the controllerAs syntax.

Something like this:

.service('statusService',function(){
     this.CANCELLATION_IN_PROCESS = function(getOrder) {
        return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
     }

Now inject the service in each controller that uses it, and bind to the view.Like this:

.controller('xyz',function($scope,statusService){
    $scope.cancellation_in_process=statusService.CANCELLATION_IN_PROCESS;
});

Your view will remain the same as before. However, this is a more DRY way and the logic (or the model) lies in the service. The controller just connects the view to the model. Since the service is a singleton, the logic is reused, rather than being creating again for each controller

Devesh Sati
  • 666
  • 4
  • 15
0

One way of doing this is to place the function in a master controller. By default the child controllers inherit from the master controller scope so the function will be available when you call it from the child controllers.

Create and define the funtion in the masterCtrl like this

app.controller('mainCtrl', ['$scope', function ($scope) {

    $scope.CANCELLATION_IN_PROCESS = function(getOrder) {
        return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
    }
}]);

Apply this, or a similar, structure the the html where masterCtrl is wrapped around the other controllers

<body ng-controller="masterCtrl">

    <div ng-controller="childCtrl1">
    ....
    <a ng-click="CANCELLATION_IN_PROCESS(yourOrder)">Test</a>
    ....

    <div ng-controller="childCtrl2">
    ....

If you need to add a custom version of the CANCELLATION_IN_PROCESS function in a controller then just add the function in that controller and apply the changes

app.controller('childCtrl2', ['$scope', function ($scope) {

    $scope.CANCELLATION_IN_PROCESS = function(getOrder) {
        return getOrder.status == 'ORDER_PLACED in child';
    }
}]);
Marcus Höglund
  • 16,172
  • 11
  • 47
  • 69
0

I don't know your exact code, so here's some dummy snippets which might suite your needs

Here's dummy snippet for service

.factory('factory_name', function() {
    var obj = {};
    var ObjFactory = {
       obj : obj
    }
});

Here's dummy snippet for controller

.controller('controller_name', function(factory_name) {
    $scope.obj = factory_name.obj;
});

now your $scope.obj can access all functions in of that factory and you can call it from view just like a controller function

Mukul Jain
  • 1,121
  • 11
  • 24