Javascript 角度重用指令和控制器
我已经编写了一个自定义下拉选项选择器,非常好,它有一些函数可以从传入的url中获取数据以填充列表 现在我想做的是重用这个组件,但是。。。 当我将其添加到应用程序的另一部分,但使用不同的数据集时,它会复制数据并多次运行控制器功能 据我所知,我有两个问题,服务是单例的,所以当我运行函数来填充一些数据时,因为只有一个服务实例,它只是将其添加到当前数据集中 然后另一个问题是控制器确实有实例,所以现在有两个实例,它在每个实例中运行函数 因此,简单的解决方案是复制组件并使用不同的名称,而这可能会解决问题,如果我想重复使用它10次,那就是相同组件的10个副本,不好 我来自OOP Java背景,所以我可能试图在不支持这些技术的语言中使用这些技术 所以我知道我必须重新思考如何做到这一点,但我遇到了一些困难,如何才能最好地解决这个问题 这里希望有一个JSFiddle可以说明我在运行什么Javascript 角度重用指令和控制器,javascript,angularjs,oop,controller,singleton,Javascript,Angularjs,Oop,Controller,Singleton,我已经编写了一个自定义下拉选项选择器,非常好,它有一些函数可以从传入的url中获取数据以填充列表 现在我想做的是重用这个组件,但是。。。 当我将其添加到应用程序的另一部分,但使用不同的数据集时,它会复制数据并多次运行控制器功能 据我所知,我有两个问题,服务是单例的,所以当我运行函数来填充一些数据时,因为只有一个服务实例,它只是将其添加到当前数据集中 然后另一个问题是控制器确实有实例,所以现在有两个实例,它在每个实例中运行函数 因此,简单的解决方案是复制组件并使用不同的名称,而这可能会解决问题,如
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
}
}
});