多个angularJS指令具有相同的功能如何

时间:2014-12-22 09:05:43

标签: javascript angularjs angularjs-directive

我有多个angularJS指令(使用其中一个有角度的chart.js版本)

现在我需要在这些指令中使用一些函数。

让我不重复自己的好方法是什么,所以从指令中删除代码并将其放在一个地方。因为该代码无论如何都是相同的。 我已经研究了范围的继承,但还没有能够解决这个问题。

这是多个指令中使用的代码:

        $scope.widgetData = false;
        $scope.graphData = false;
        $scope.graphSelectorIndex = 0;

        $scope.graphSelector = [
            { 'byPeriod' : 'Periode'},
            { 'byHour' : 'Uur' },
            { 'byDay' : 'Dag'}
        ];

        $scope.graphSelectorByText = function (text) {
            switch (text) {
                case ('byPeriod'):
                    $scope.selector = 'byPeriod'
                    $scope.graphData = $scope.allGraphData.byPeriod;
                    $scope.graphType = 'Line';
                    break;
                case ('byDay'):
                    $scope.selector = 'byDay'
                    $scope.graphData = $scope.allGraphData.byDay;
                    $scope.graphType = 'Line';
                    break;
                case ('byHour'):
                    $scope.selector = 'byHour'
                    $scope.graphData = $scope.allGraphData.byHour;
                    $scope.graphType = 'Bar';
                    break;
            }
        }

        $scope.graphSelectorByInt = function (int) {
            switch (int) {
                case (0):
                    $scope.selector = 'byPeriod';
                    $scope.graphData = $scope.allGraphData.byPeriod;
                    $scope.graphType = 'Line';
                    break;
                case (1):
                    $scope.selector = 'byDay';
                    $scope.graphData = $scope.allGraphData.byDay;
                    $scope.graphType = 'Line';
                    break;
                case (2):
                    $scope.selector = 'byHour';
                    $scope.graphData = $scope.allGraphData.byHour;
                    $scope.graphType = 'Bar'
                    break;
            }
        }

        $scope.graphSelectorPrev = function () {
            $scope.graphSelectorIndex--;
            if ($scope.graphSelectorIndex < 0) {
                $scope.graphSelectorIndex = $scope.graphSelector.length-1;
            }
            $scope.graphSelectorByInt($scope.graphSelectorIndex);
            console.log($scope.graphSelectorIndex);

        }

        $scope.graphSelectorNext = function () {
            $scope.graphSelectorIndex++;
            if ($scope.graphSelectorIndex >= $scope.graphSelector.length) {
                $scope.graphSelectorIndex = 0;
            }
            $scope.graphSelectorByInt($scope.graphSelectorIndex);
            console.log($scope.graphSelectorIndex);
        }

一些html:

    <div class="controls">
        <span class="btn_arrow previous inactive" ng-click="graphSelectorPrev()">Vorige</span>
        <p>{+ selector +}</p>
        <span class="btn_arrow next" ng-click="graphSelectorNext()">Volgende</span>
    </div>

感谢任何可以提供帮助的人!

4 个答案:

答案 0 :(得分:1)

首先,在这种情况下,你可以这样做一些干:

HTML:

<div class="controlls"> <span class="btn_arrow previous inactive" ng-click="graphSelectorInc(-1)">Vorige</span>

    <p>{{ selector }}</p> <span class="btn_arrow next" ng-click="graphSelectorInc(+1)">Volgende</span>

</div>

JS:

//Warning this approach is so called not monomorh(polymorph): the parameter of function is not strictly typed, so it lacks browser optimizations but in this case its not so important because code won't run often
$scope.graphSelectorByAny = function (step) {
    switch (step) {
        case ('byPeriod'):
        case (0):
            $scope.selector = 'byPeriod'
            $scope.graphData = $scope.allGraphData.byPeriod;
            $scope.graphType = 'Line';
            break;
        case ('byDay'):
        case (1):
            $scope.selector = 'byDay'
            $scope.graphData = $scope.allGraphData.byDay;
            $scope.graphType = 'Line';
            break;
        case ('byHour'):
        case (2):
            $scope.selector = 'byHour'
            $scope.graphData = $scope.allGraphData.byHour;
            $scope.graphType = 'Bar';
            break;
    }
}

$scope.graphSelectorInc = function (inc) {
    $scope.graphSelectorIndex += inc;
    if ($scope.graphSelectorIndex < 0) {
        $scope.graphSelectorIndex = $scope.graphSelector.length - 1;
    } else if ($scope.graphSelectorIndex >= $scope.graphSelector.length) {
        $scope.graphSelectorIndex = 0;
    }
    $scope.graphSelectorByAny($scope.graphSelectorIndex);
    console.log($scope.graphSelectorIndex);

}

我为你做了JSFiddle

但是有一个单独的指示也很好,我不能写,因为我不知道你想要在控制器中想要什么数据。 Yo可以阅读指令和数据绑定from the official docs

另外考虑使用services你希望乘法控制器/指令做同样的事情。

希望它会对你有所帮助。

答案 1 :(得分:1)

如果不知道指令之间的确切差异(也许你甚至不需要多个)我会建议使用服务或者只是创建一个控制器并将其添加到指令模板。

如果您获得了在指令之间共享状态的一些好处,我只会选择服务,否则我会选择控制器。

以下是我使用控制器&#39; (在jsfiddle上测试):

angular.module('myApp', [])
.controller('sharedCtrl', function() {
    var self = this;

    // $scope.doIt = ...
    self.doIt = function (msg) {
      alert(msg);
    };
})
.directive('dir1', function () {
    return {
        restrict: 'E',
        template: '<div ng-controller="sharedCtrl as ctrl"><button ng-click="ctrl.doIt(msg)">dir1</button></div>',
        scope: {},
        link: function (scope) {
            scope.msg = 'Hi, I\'m dir1!';
        }
    };
})
.directive('dir2', function () {
    return {
        restrict: 'E',
        template: '<div ng-controller="sharedCtrl as ctrl"><button ng-click="ctrl.doIt(msg)">dir2</button></div>',
        scope: {},
        link: function (scope) {
            scope.msg = 'Hi, I\'m dir2!';
        }
    };
});

如果需要从指令范围传递内容,可以将其简单地传递给控制器​​函数。

P.S。:我更喜欢controller as语法而不是$scope。如果您不熟悉它,可以将self替换为$scope,但我建议您进一步了解controller as

答案 2 :(得分:0)

我个人喜欢服务方式。

请参阅:http://jsfiddle.net/elennaro/b48jex3w/33/

以下是代码:

HTML

<div ng-controller="BaseCtrl">
<div class="controlls"> <span class="btn_arrow previous inactive" ng-click="graphSelectorInc(-1)">Vorige</span>

    <p>{{ selector }}</p> <span class="btn_arrow next" ng-click="graphSelectorInc(+1)">Volgende</span>

</div>

JS

angular.module('myApp', [])
.service('GraphSelector', function () {
var graphSelectorIndex = 0;
var graphSelector = [{
    'byPeriod': 'Periode'
}, {
    'byHour': 'Uur'
}, {
    'byDay': 'Dag'
}];
return {
    selector: this.selector,
    inc: function (inc) {
        graphSelectorIndex += inc;
        if (graphSelectorIndex < 0) {
            graphSelectorIndex = graphSelector.length - 1;
        } else if (graphSelectorIndex >= graphSelector.length) {
            graphSelectorIndex = 0;
        }
        console.log(Object.keys(graphSelector[graphSelectorIndex]));
        return graphSelector[graphSelectorIndex][Object.keys(graphSelector[graphSelectorIndex])[0]];
    }

}
}).controller('BaseCtrl', function ($scope, GraphSelector) {

$scope.graphSelectorInc = function (inc) {
    $scope.selector = GraphSelector.inc(inc);

}});

你看我有一个服务GraphSelector是一个单例,它存储graphSelectorIndex和graphSelector对于所有将给他打电话的所有控制器/指令都是一样的。

因此,您可以从任何想要切换当前选择器属性的地方调用此服务。

我使用Object.keys只获取返回给控制器的当前选择器状态的值。但是如果你想要,你可以返回整个对象并获得控制器中的值。

Angular JS服务是一个强大的工具,可以获得干净且可读的代码,我经常使用它来在控制器之间共享一些数据。

答案 3 :(得分:0)

您可以创建一个包含可重用逻辑的共享控制器,然后将其动态链接到您的指令。

所以你的控制器将是:

app.controller('sharedCtrl', function($scope) {
    $scope.widgetData = false;
    $scope.graphData = false;
    $scope.graphSelectorIndex = 0;

    $scope.graphSelector = [
        { 'byPeriod' : 'Periode'},
        { 'byHour' : 'Uur' },
        { 'byDay' : 'Dag'}
    ];

    $scope.graphSelectorByText = function (text) {
        switch (text) {
            case ('byPeriod'):
                $scope.selector = 'byPeriod'
                $scope.graphData = $scope.allGraphData.byPeriod;
                $scope.graphType = 'Line';
                break;
            case ('byDay'):
                $scope.selector = 'byDay'
                $scope.graphData = $scope.allGraphData.byDay;
                $scope.graphType = 'Line';
                break;
            case ('byHour'):
                $scope.selector = 'byHour'
                $scope.graphData = $scope.allGraphData.byHour;
                $scope.graphType = 'Bar';
                break;
        }
    }

    $scope.graphSelectorByInt = function (int) {
        switch (int) {
            case (0):
                $scope.selector = 'byPeriod';
                $scope.graphData = $scope.allGraphData.byPeriod;
                $scope.graphType = 'Line';
                break;
            case (1):
                $scope.selector = 'byDay';
                $scope.graphData = $scope.allGraphData.byDay;
                $scope.graphType = 'Line';
                break;
            case (2):
                $scope.selector = 'byHour';
                $scope.graphData = $scope.allGraphData.byHour;
                $scope.graphType = 'Bar'
                break;
        }
    }

    $scope.graphSelectorPrev = function () {
        $scope.graphSelectorIndex--;
        if ($scope.graphSelectorIndex < 0) {
            $scope.graphSelectorIndex = $scope.graphSelector.length-1;
        }
        $scope.graphSelectorByInt($scope.graphSelectorIndex);
        console.log($scope.graphSelectorIndex);

    }

    $scope.graphSelectorNext = function () {
        $scope.graphSelectorIndex++;
        if ($scope.graphSelectorIndex >= $scope.graphSelector.length) {
            $scope.graphSelectorIndex = 0;
        }
        $scope.graphSelectorByInt($scope.graphSelectorIndex);
        console.log($scope.graphSelectorIndex);
    }

});

你的指令看起来像这样:

app.directive('myDirective', function() {
    return {
         restrict: 'E',
         controller: '@',
         name: 'myDirectiveCtrl',
         link: function($scope, $element, $attrs) {
             // add directive specific logic
         }
    }
});

然后标记看起来像这样:

<my-directive my-directive-ctrl="sharedCtrl"></my-directive>