到目前为止,研究现有的stackoverflow答案总能帮助我,我总能找到答案,但现在我真的被卡住了。
我正在构建一个应用程序,它使用指令创建日历月类型框。
<app2directive class="column_50" jahr="2016" mon="November"></app2directive>
指令代码因此隔离范围并利用templateUrl文件绘制日历月
App.directive('app2directive',function( YEARS, MONTHS, DAYS){
return {
restrict:"ACE",
scope:{},
replace:true,
templateUrl:"templates/cal_directive3.html",
controller: function ( $scope, $attrs, $injector, $log, YEARS, MONTHS, DAYS) { var factoryName = "datumFactory" ;
var factoryTonnen = "jsonsrc" ;
var factoryInstance = $injector.get( factoryName ) ;
var tonnenInstance = $injector.get( factoryTonnen ) ;
var wtf = $scope.jsondata.get().then( function( promise){
console.log( "jsondata", promise ) ;
//$scope.tonnen = promise ;
}, function( error){
console.log( "error", error ) ;
}) ;
});
目前我使用$ injector注入一个工厂,该工厂运行$ http-request来读取json文件,其中包含假期或特定于所选年份和月份的其他静态信息等数据。
App.factory( 'jsonsrc', function( $http, $q ){
return {
get: function(){
var deferred = $q.defer() ;
$http.get( 'termine_2016.json' )
.success(function(data, status, headers, config) {
deferred.resolve( data ) ;
}).error(function(data, status, headers, config) {
console.log( "[jsonsrc] request didnot work!" );
deferred.reject( data ) ;
}) ;
return deferred.promise ;
}
}
});
它的效果是,对于全年页面加载,对$ http的同一调用运行12次。
我关心的是重构文件,以便我可以优选地将json数据加载到主控制器中,并且指令范围可以从父作用域继承。
本质上,呼叫返回一个承诺。该指令需要等待该承诺在其继续进行之前解决的手段,但现在我仍然坚持如何去做。提前感谢任何指针!
答案 0 :(得分:1)
首先$ http已经返回了你可以做的承诺:
return $http.get(...)
PS:你可以链接承诺,所以如果你有一些预处理可以做
return $http.get(..).then(function(response){
var data = response.data;
[..process..]
**return data;**
}, function(rejection){
// do some stuff
});
第二:通常你将数据绑定到你的指令(例如ng-model),并在控制器中调用服务(我认为是视图控制器)。为了处理数据的异步加载,你使用范围。$ watch或attrs。$观察模型,用加载的数据刷新你的指令。
这强制不会将指令绑定到您的数据加载方式,使其可重复使用,无论您加载数据的方式如何或在应用程序上更改它。
请注意我以粗体显示的内容,您不会忘记,或者下一次调用将不会处理您的数据。
最后:通常由指令API提供的链接功能你可以拥有:
link : function(scope, element, attrs){
attrs.$observe('myVariable', function(){
// refresh your internal state of the directive here
});
}
'myVariable'意味着在你的指令调用中你有一个attr my-variable:
和“myData”在视图控制器中加载如下:
jsonrc.get().then(function(response){
$scope.myData = response.data;
});
如果您想要更进一步,我建议您为假期服务构建服务,以便仅在应用程序启动时加载数据:
App.service('MyService',['$http', function($http){
var promise = $http.get([URL]);
return function(){ // this is your service
var me = this;
promise.then(function(response){
this.data = response.data;
});
}
}]);
现在您可以在主控制器中使用:scope.data = MyService.data;或者甚至在你的指令中使用它,或者如果你想要使用一些吸气剂,这通常会更好,但并不总是令人骄傲。
如果我忘了什么告诉我。
答案 1 :(得分:0)
我认为这可能有所帮助。
scope: {
data: '=',
}
&#13;
$scope.directiveData = {}
<mydirective data="directiveData"></mydirective>
data
名称或链接上的scope.data
。可能你需要为directiveData模拟数据,或者只是添加一个ng-if来防止崩溃(当第一次尝试显示数据时,并且directiveData是空对象)。
答案 2 :(得分:0)
让您的工厂保存httpPromise并仅创建一次。
App.factory( 'jsonsrc', function( $http ){
var httpPromise;
function load () {
httpPromise = $http.get( 'termine_2016.json' )
.then(function onFullfilled(response) {
//return data for chaining
return response.data;
}).catch( function onRejected(response) {
console.log( "[jsonsrc] request didnot work!" );
//throw to reject promise
throw response.status;
});
return httpPromise;
};
function get () {
if (httpPromise) return httpPromise;
//Otherwise
return load();
};
return { load: load,
get: get
};
});
请注意,我删除了$q.defer
,而是使用了.then
和.catch
方法。已弃用.success
和.error
方法;请参阅AngularJS $http Service API Reference -- deprecation notice。
然后您可以简化您的指令:
App.directive('app2directive',function(){
return {
restrict:"ACE",
scope:{},
replace:true,
templateUrl:"templates/cal_directive3.html",
controller: function ($scope, $attrs, jsonsrc, $log, YEARS, MONTHS, DAYS) {
jsonsrc.get().then (function (data) {
$scope.tonnen = data ;
}).catch ( function(error){
console.log( "error", error ) ;
});
})
}
});
以这种方式实现,jsonsrc
工厂只执行一次XHR GET,但app2directive
的每个实例都可以检索其自己的隔离范围的数据。