Javascript 角度重用指令和控制器

Javascript 角度重用指令和控制器,javascript,angularjs,oop,controller,singleton,Javascript,Angularjs,Oop,Controller,Singleton,我已经编写了一个自定义下拉选项选择器,非常好,它有一些函数可以从传入的url中获取数据以填充列表 现在我想做的是重用这个组件,但是。。。 当我将其添加到应用程序的另一部分,但使用不同的数据集时,它会复制数据并多次运行控制器功能 据我所知,我有两个问题,服务是单例的,所以当我运行函数来填充一些数据时,因为只有一个服务实例,它只是将其添加到当前数据集中 然后另一个问题是控制器确实有实例,所以现在有两个实例,它在每个实例中运行函数 因此,简单的解决方案是复制组件并使用不同的名称,而这可能会解决问题,如

我已经编写了一个自定义下拉选项选择器,非常好,它有一些函数可以从传入的url中获取数据以填充列表

现在我想做的是重用这个组件,但是。。。 当我将其添加到应用程序的另一部分,但使用不同的数据集时,它会复制数据并多次运行控制器功能

据我所知,我有两个问题,服务是单例的,所以当我运行函数来填充一些数据时,因为只有一个服务实例,它只是将其添加到当前数据集中

然后另一个问题是控制器确实有实例,所以现在有两个实例,它在每个实例中运行函数

因此,简单的解决方案是复制组件并使用不同的名称,而这可能会解决问题,如果我想重复使用它10次,那就是相同组件的10个副本,不好

我来自OOP Java背景,所以我可能试图在不支持这些技术的语言中使用这些技术

所以我知道我必须重新思考如何做到这一点,但我遇到了一些困难,如何才能最好地解决这个问题

这里希望有一个JSFiddle可以说明我在运行什么

var app = angular.module('myApp',[]);

app.directive('mySelector', function () {
return {
 scope: {
      mydata: '='
    },
    restrict: 'EA',
    template:'<select ng-model="timePeriodSelection" ng-options="timePeriodOption.name for timePeriodOption in timePeriodOptions"><option value="">Choose time period</option></select>',
controller: function($scope, myService) {
    //$scope.name = 'Superhero';
    console.log('test',$scope.mydata);
    myService.setData($scope.mydata);
    $scope.timePeriodOptions = myService.getData();
  console.log('test2',myService.getData());
    }
 };
});

app.factory('myService', function() {
var _data=[];    
return {
    setData: function(value){
        for (var a=0;a<value.length;a++){
            _data.push(value[a]);
        }
    },
    getData: function(){
        return _data
    }            
}
});

出于商业原因,我无法向您展示我的代码,但想象一下,我传递的实际上是一个url,我有一个服务,它获取数据,然后将数据存储在服务/工厂的数组中,每次运行时,它都会不断地将数据相加!该代码是一个模拟演示。

类似于自定义下拉列表的内容应该是一个指令,而不是其他内容。也就是说,有很多方法可以实现您试图通过指令实现的目标。检查一下,他们真的很有帮助

在某种程度上,您可能希望有一个隔离作用域,使用一个模板,并添加一个链接函数

项目始终相同的示例:

angular.module('myApp')
    .directive('myDropdown', function () {
        return {

            scope: {},

            template: '' +
                '<div class="my-dropdown">' +
                    '<div class="my-dropdown-item" ng-repeat="item in items">{{item.text}}</div>' +
                '</div>',

            link: function (scope, element, attrs) {
                scope.items = ['Item 1', 'Item 2', 'Item 3'];
            }

        };
    });
将项目传递给每个实例的示例:

angular.module('myApp')
    .directive('myDropdown', function () {
        return {

            scope: {
                items: '='
            },

            template: '' +
                '<div class="my-dropdown">' +
                    '<div class="my-dropdown-item" ng-repeat="item in items">{{item.text}}</div>' +
                '</div>'

        };
    });
-更新-

在服务中一次获取数据的示例:

angular.module('myApp')
    .service('dataService', function ($http) {
        var items;

        $http.get('http://ab.com/dropdown-items')
        .then(function (res) {
            items = res.data;
        });

        return {
            items: items
        };
    })
    .directive('myDropdown', function (dataService) {
        return {

            scope: {},

            template: '' +
                '<div class="my-dropdown">' +
                    '<div class="my-dropdown-item" ng-repeat="item in items">{{item.text}}</div>' +
                '</div>',

            link: function (scope, element, attrs) {
                scope.items = dataService.items;
            }

        };
    });

因此,除非有人能以不同的方式告诉我,否则我能看到的解决这个问题的唯一方法是将数据保存在控制器中,因此将数据隔离到其自己的控制器实例中。将数据保存在任何其他地方只会导致实例问题

我重构了我的“fiddle”,以显示两个不同的数据源。在本例中,我使用了两个工厂作为模型,将数据带回控制器进行处理,然后存储

通常情况下,如果我不重用组件,我会将此逻辑放入工厂,但这样做会给我带来一个问题,我必须从开始

此外,在我的“真实”项目中,我检查变量以“查看”触发了什么“实例”并从中调用方法,所有这些看起来都有点笨拙,但这似乎是我使其工作的唯一可靠方法,也许Angular 2可以解决这些问题


你能提供你所有的代码并在plunker中突出这个问题吗?您可以分叉和编辑这一个,可惜不是因为它的源代码是封闭的,但是我已经用一些东西设置了一个JSFIDLE来演示我的问题,好吧,我有一些类似的东西,但是我在哪里保存数据呢?我们被告知将数据保存在工厂/服务中,但这样做会给我带来重复问题,我需要在其他服务中访问此数据以访问其他服务。您能否给出一个更具体的示例,说明您所谈论的数据类型?用户输入的数据,组成下拉选择的数据,还有其他什么?这些数据来自返回XML的服务,我将其转换为json,然后将数组存储在工厂中,问题出现了,因为控制器中存在获取数据的调用,这是因为控制器有多个实例,多次调用并添加到数组中。继续。我目前的解决方法是使用一个变量,传递到控制器中,以确定正在使用哪个实例,然后对该实例发出数据请求,我觉得有点“笨拙”,但我能看到的唯一解决问题的方法是将数据存储在控制器中,这再次,我听说这是一种不好的做法。也许打电话来获取服务中的数据,然后让您的指令使用该服务。请参阅更新的答案。
    var app = angular.module('myApp',[]);

app.directive('mySelector', function () {
return { 
    scope: true,
    bindToController:  {
        mydata: '@mydata',     
        timePeriodOptions: '='
    },
    controllerAs: 'selCtrl',
    restrict: 'EA',
    template:'<select ng-model="timePeriodSelection" ng-options="timePeriodOption.name for timePeriodOption in selCtrl.timePeriodOptions"><option value="">Choose time period</option></select>',
    controller: 'selCtrl'
 };
});    
app.controller('selCtrl', function($scope, myService) {
    var selCtrl = this;    
    selCtrl.timePeriodOptions = [];
    if (angular.isString(selCtrl.mydata)){
        processData();
    }
    function processData(){
        var value = myService.getData(selCtrl.mydata);
        for (var a=0;a<value.length;a++){
            selCtrl.timePeriodOptions.push(value[a]);
        }
    };
});

app.factory('myService', function(dataModel1,dataModel2) {
return {
    getData: function(model){
        var _data = []        
        if (model === "1"){
            _data = dataModel1.getData();
        }else{
            _data = dataModel2.getData();
        }
        console.log('data ',_data);
        return _data
    }            
    }
});
app.factory('dataModel1', function() {
    var _data=[{"name":1,"value":1},{"name":2,"value":2},{"name":3,"value":3}];    
    return {
        getData: function(){
            return _data
        }            
    }
});
app.factory('dataModel2', function() {
    var _data=[{"name":4,"value":4},{"name":5,"value":5},{"name":6,"value":6}];    
    return {
        getData: function(){
            return _data
        }            
    }
});