Javascript 角度指令相关请求
我为以下小部件属性创建了自定义指令:Javascript 角度指令相关请求,javascript,angularjs,directive,Javascript,Angularjs,Directive,我为以下小部件属性创建了自定义指令: <div widget></div> htmlTemplate是基本的html代码,也使用自定义指令(例如标记): 在响应处理程序中,我将结果绑定到范围。 我现在面临的问题是,该指令也请求数据,但该请求取决于从Offer.query()接收到的数据。 例如,来自Offer.query()的响应返回一个ID(我们称之为myID),seal指令需要该ID来请求更多数据。 因此,我只需将所有逻辑放在callback Offer.query
<div widget></div>
htmlTemplate是基本的html代码,也使用自定义指令(例如
标记):
在响应处理程序中,我将结果绑定到范围。
我现在面临的问题是,该指令也请求数据,但该请求取决于从Offer.query()接收到的数据。
例如,来自Offer.query()的响应返回一个ID(我们称之为myID),seal指令需要该ID来请求更多数据。
因此,我只需将所有逻辑放在callback Offer.query回调函数中。这似乎不是最好的方法
所以我想把这部分移到
指令的link函数:
skdApp.directive("widget", function() {
return {
restrict: 'A',
template: htmlTemplate,
link: function($scope, element, attri) {
/*
* setup event handler and twitter bootstrap components here
*/
}
}
skdApp.directive("seal", function() {
var sealHTML = '<div>{{offer.data.foobar}}</div>';
return {
restrict: 'E',
template: sealHTML,
link: function($scope, element, attrs) {
$scope.$watch('offer.myId', function (newValue, oldValue) {
if (typeof newValue !== "undefined") {
/* request more data with myId
* and bind the result to offer.data
*/
}
});
}
});
skdApp.指令(“seal”,函数(){
var sealHTML='{{offer.data.foobar}}';
返回{
限制:'E',
模板:sealHTML,
链接:函数($scope,element,attrs){
$scope.$watch('offer.myId',函数(newValue,oldValue){
if(newValue的类型!=“未定义”){
/*使用myId请求更多数据
*并将结果绑定到offer.data
*/
}
});
}
});
这种方法是“angular”兼容的,还是在angular中有其他更好的方法(在结构方面)来实现这一点?您可以在child指令中查看offer.myId,因为父(小部件)和子(密封)共享相同的作用域。默认情况下,该指令不会创建新的作用域 我认为您可以广播自定义事件来通知child指令,并在需要时隔离作用域,以避免作用域碰撞
我将采用这种反向危险风格(以答案的形式提出的问题)。我一直在思考最近看到的这个问题的解决方案。它显然有效,但它有一些行为特征,我第一次尝试将其标记为“错误”.经过更深入的思考,我意识到在一些非常具体的场景中,这些特征可能是可取的 我当然不会将此作为一种通用解决方案,在每次需要绑定异步返回的数据时使用。我介绍它是为了强调这样一个事实,即此场景提出的问题有多个可能的答案。在某些情况下,可能需要真正的业务逻辑来阻止UI呈现,直到服务调用返回。在其他情况下,让UI保持活动状态并响应无关的工作可能更合适 例如,在订单处理系统中,我可能很想阻止客户端线程与视图元素交互,直到知道销售事务的结果为止。对于基于web的电子表格应用程序和服务器端公式计算,情况并非如此 我认为解决这一需求的异步和同步模式能够共存是一件美妙的事情。也就是说,返回承诺对象并没有强制客户机使用它,就像将返回值放在范围中强制客户机监视它们一样 下面的内容演示了一种与前面探讨的异步
watch()
样式同步处理此需求的方法:
var servicesModule = servicesModule || angular.module('myModule', []);
servicesModule.factory('thingClient',
['$http', '$q', function( $http, $q ) {
return new ThingClient($http, $q);
}]
);
function ThingClient($http, $q) {
function callService(scopeObject) {
var defer = $q.defer();
var promise = defer.promise;
$http({
method: 'POST',
url: 'http://at/some/url/',
data: { x: 'y', y: 'z', z: 'x', one: 1, two: 2, three: 3},
cache: false
}, function(data) {
scopeObject.data = data;
defer.resolve(data);
}, function() {
scopeObject.data = null;
defer.resolve(null)
});
return promise;
}
}
client-service.js
function ConsumingController( $scope, thingClient ) {
// Be careful to use an object (so you have data wrapped such that it
// is eligible for prototypical inheritance and call by reference without
// passing the scope itself). Leave the 'data' element undefined so you
// can trigger the transition from undefined -> null in the failure case
// and not just the on-success case.
$scope.dto = { data: undefined };
var promise = thingClient.callService(scope.dto);
// Asynchronous strategy
$scope.$watch('offer.myId', function (newValue, oldValue) {
if( newValue == null ) {
// Fail!
} else {
// Succeed!
}
}
// Synchronous strategy
if( promise.then(
function(data) {
if( data == null ) {
// Fail
} else {
// Succeed
}
}
}
}
使用controller.js您将服务器交互封装到一个服务中,您的控制器很好而且“薄”,并且您的指令$watch()允许$scope更改以触发一些操作。我喜欢它。
var servicesModule = servicesModule || angular.module('myModule', []);
servicesModule.factory('thingClient',
['$http', '$q', function( $http, $q ) {
return new ThingClient($http, $q);
}]
);
function ThingClient($http, $q) {
function callService(scopeObject) {
var defer = $q.defer();
var promise = defer.promise;
$http({
method: 'POST',
url: 'http://at/some/url/',
data: { x: 'y', y: 'z', z: 'x', one: 1, two: 2, three: 3},
cache: false
}, function(data) {
scopeObject.data = data;
defer.resolve(data);
}, function() {
scopeObject.data = null;
defer.resolve(null)
});
return promise;
}
}
function ConsumingController( $scope, thingClient ) {
// Be careful to use an object (so you have data wrapped such that it
// is eligible for prototypical inheritance and call by reference without
// passing the scope itself). Leave the 'data' element undefined so you
// can trigger the transition from undefined -> null in the failure case
// and not just the on-success case.
$scope.dto = { data: undefined };
var promise = thingClient.callService(scope.dto);
// Asynchronous strategy
$scope.$watch('offer.myId', function (newValue, oldValue) {
if( newValue == null ) {
// Fail!
} else {
// Succeed!
}
}
// Synchronous strategy
if( promise.then(
function(data) {
if( data == null ) {
// Fail
} else {
// Succeed
}
}
}
}