【问题标题】:AngularJS directive that formats after API call在 API 调用后格式化的 AngularJS 指令
【发布时间】:2014-06-18 17:57:09
【问题描述】:

我需要一个将 API 请求作为 $parsers 函数执行的指令。

<input type="text" name="referer" id="referer" ng-model="Subscribe.user.referer" check-referer>

我的指令看起来像

app.directive('checkReferer', [ 'subscriptionService', function( subscriptionService ) {
return {
        restrict: 'A',
        require: 'ngModel',
        link: function( scope, element, attrs, ngModel ) {
            ngModel.$parsers.unshift( function( viewValue ) {
                subscriptionService.checkReferer( viewValue )
                    .then(function( response ) {
                        if ( typeof response.data == 'object') {
                            ngModel.$setValidity('validReferer', true );
                            return viewValue;
                        }
                    });
             });
}])

为了便于阅读,我稍微缩短了代码。该服务非常简单(在服务内部):

subscriptionService.checkReferer: function( email ) {
    var promise = $http.get( settings.ApiUrl + 'check-referer/' + email )
        .then( function( response ) {
            return response;
        }, function(response) {
            // error handling here
        })
    return promise;
 },

问题是:当我在加载承诺后“返回 viewValue”时,$modelValue 不会改变,所以基本上承诺不会改变通过 ng-model 传递给指令的 Subscribe.user.referer。如果我返回与承诺不同的任何东西,一切都很好,所以问题就在那里,不知道如何解决它:(

如果我将想要更改的值作为属性传递给指令的范围,我没有问题。但这不是我想要这样做的方式:)

我对 Angular 不是很熟悉,但我已经使用了一段时间了。我花了整个上午试图自己找到答案。没运气。有点沮丧。

非常感谢任何帮助。

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    您没有将数据恢复到指令中的原因是,服务需要时间将承诺返回给指令,在此期间,角度已经执行了两种方式绑定。这是常见的问题之一异步调用。

    因此,有多种解决方案可以让您的服务本质上是同步的

    xhr.open(method, url, true);
    

    看看这个link

    Nest 解决方案是 等到数据到达服务中

    // Make a remote request.
    $http.get('some wonderful URL for a service').then(function (results) {
      superImportantInfo = results;
    
      semaphore = true;
    });
    
    while (!semaphore) {
      // We're just waiting.
    }
    

    另一种解决方案

    var retrieveEventDetails = function(events) {
        // events is array
    
        var deferred = $q.defer();
        var promise = deferred.promise;
    
        var retrieveData = function(data) {
            return function(){      
                return $http({
                    url: '/api/eventdetails',
                    method: 'POST',
                    data: {
                        event_number: data.number
                    },
                    isArray: true
                })
            }
        }
    
        deferred.resolve();
    
        return events.reduce(function(promise, single_event){
            return promise.then(retrieveData(single_event));
        }, promise);
    }
    

    希望对您有所帮助!

    【讨论】:

    • 感谢您的宝贵时间,先生!我真的很喜欢“另一种解决方案”,但我有点想保持异步。我的观点是使用 Angular 内置的 $parsers 异步更新模型。很多人使用信号,我不喜欢。我通过指令范围传递模型来做到这一点,但仍然觉得“不优雅”:)
    猜你喜欢
    • 2014-04-20
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多