【问题标题】:Delay directive/div until scope value available延迟指令/div,直到范围值可用
【发布时间】:2015-05-13 23:16:07
【问题描述】:

我有一个需要 soundcloud url 的 soundcloud 自定义指令。 soundcloud url 是通过 $http 服务从数据库中获取的,但是,soundcloud 自定义指令的 div 已加载,并且在定义之前需要 soundcloud url 的值。

我得到的 Plangular 指令代码在这里: https://github.com/jxnblk/plangular/blob/master/src/plangular.js *我没有开发这个

这是我的 HTML 代码:

<div plangular="{{soundcloud}}">
<button ng-click="playPause()">Play/Pause</button>
<progress ng-value="currentTime / duration || 0">
{{ currentTime / duration || 0 }}
</progress>
</div>

这是 Angular 代码:

displaySong.controller('song', ['$scope', '$http', 'fetchSong', function($scope, $http, fetchSong) {
    $scope.songID
    $scope.songName;

    //Controller properties
    $scope.songPromise; //The song promise for fetching

    $scope.init = function(songID, userID) {
        $scope.songID = songID;
        $scope.userID = userID;
        $scope.songPromise = $http({
            method: "post",
            url: fetchSong,
            data: {
                song_id: $scope.songID
            },
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        }).then(function(successResponse) {
            console.log('Successfully fetched song');
            console.log(successResponse);
            var song = successResponse.data;
            $scope.songID = song.song_id;
            $scope.songName = song.song_name;
            $scope.songType = song.song_type;
            $scope.songEmbed = song.song_embed;
            $scope.soundcloud = song.song_embed;
        }, function(errorResponse) {
            console.log('Error fetching');
            $scope.songID = null;
        });
    };
}]);

我知道这是异步性质的问题,因为当我在歌曲控制器的开头添加这一行时:

$scope.soundcloud = "https://soundcloud.com/jshigley/shine";

它工作得很好。我还注意到,当我向指令中出现的播放/暂停按钮发送垃圾邮件时,我收到多个控制台错误“HTTP 404 Not Found”,这让我相信它正在尝试查找未定义 url

因为它是一个 div 指令而不是一个函数调用,所以我不能使用诸如将 then 链接到我的 $scope.songPromise 的承诺。我曾考虑将其放入控制器并让控制器执行 $timeout 5 秒之类的操作,但我认为这不会延迟 DOM 的执行。

soundcloud URL 最终会被加载,但它在 plangular 指令的眼中仍未定义(我实际上遇到了很多此类问题,因为加载范围和指令的时机不好)。任何 Angular 奇才愿意教我如何驯服 AngularJS 的异步特性?

【问题讨论】:

  • 您是否尝试过将 ngShow 用于绑定到您的 $http 请求履行承诺后声明的值的 div?
  • plangular指令代码在这里:github.com/jxnblk/plangular/blob/master/src/plangular.js,不是我开发的
  • ngShow 是否阻止 div plangular 执行?我以为它只是隐藏了div,但并没有阻止里面的代码被加载
  • 在下面查看我的答案。 ngShow 不会停止 plangular 的执行,但它会阻止 div 显示,直到所有信息都已加载,假设您的 $http 请求正常运行

标签: javascript jquery angularjs asynchronous


【解决方案1】:

您可以在自定义指令中使用 $watch 来观察 url 属性何时更改。 在

    link: function(scope, el, attr) {

改变

if (src) {
    resolve({ url: src, client_id: client_id }, function(err, res) {
      if (err) { console.error(err); }
      scope.$apply(function() {
        scope.track = createSrc(res);
        if (Array.isArray(res)) {
          scope.tracks = res.map(function(track) {
            return createSrc(track);
          });
        } else if (res.tracks) {
          scope.playlist = res;
          scope.tracks = res.tracks.map(function(track) {
            return createSrc(track);
          });
        }
      });
    });
  }

 scope.$watch('attr.plangular', function(newVal) {

    resolve({ url: attr.plangular, client_id: client_id }, function(err, res) {
      if (err) { console.error(err); }
      scope.$apply(function() {
        scope.track = createSrc(res);
        if (Array.isArray(res)) {
          scope.tracks = res.map(function(track) {
            return createSrc(track);
          });
        } else if (res.tracks) {
          scope.playlist = res;
          scope.tracks = res.tracks.map(function(track) {
            return createSrc(track);
          });
        }
      });
    });
 }, true);

如果您不想更改指令,那么您可能只想在获取 url 时使用 ng-if 来加载该 plangular div。

<div plangular="{{soundcloud}}" ng-if="haveurl">

在角码中:

}).then(function(successResponse) {
        console.log('Successfully fetched song');
        console.log(successResponse);
        $scope.haveurl = true;

【讨论】:

  • 这将包含在指令的链接功能中,一旦检测到会自动更改?我对指令有点陌生,但仍然不完全理解它们。 plangular 的指令代码在这里:github.com/jxnblk/plangular/blob/master/src/plangular.js,很抱歉占用您的时间,但如果您有的话,如果您能帮助我,将不胜感激?
【解决方案2】:

尝试像这样使用ng-show,仅在您的$http 请求完成后才显示div

<div ng-show="httpRequestComplete" plangular="{{soundcloud}}">
<button ng-click="playPause()">Play/Pause</button>
<progress ng-value="currentTime / duration || 0">
{{ currentTime / duration || 0 }}
</progress>
</div>

displaySong.controller('song', ['$scope', '$q', '$http', 'fetchSong', function($scope, $http, fetchSong) {
    /* add $q promise library */

    $scope.songID
    $scope.songName;

    var httpRequest = function() {
         var deferred = $q.defer();
         $http({
            method: "post",
            url: fetchSong,
            data: {
                song_id: $scope.songID
            },
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        }).success(function(successResponse) {
            deferred.resolve({response: successResponse});
            console.log('Successfully fetched song', successResponse);
            var song = successResponse.data;
            $scope.songID = song.song_id;
            $scope.songName = song.song_name;
            $scope.songType = song.song_type;
            $scope.songEmbed = song.song_embed;
            $scope.soundcloud = song.song_embed;
        }).error(function(error) {
            console.log(error);
        });
        return deferred.promise;
    };

    httpRequest().then(function(response) {
          $scope.httpRequestComplete = true;
          console.log('div will show');
    };



}]);

我会做这样的事情,将div 的显示延迟到httpRequestComplete = true,或者直到你的承诺($q)得到履行。这将确保在您获得可用信息之前不会加载您的 div

【讨论】:

  • 我虽然显示/隐藏 div 不会阻止指令被执行?
  • 我看到了你的问题,我相信@kwan245 有使用 $watch 或使用 ng-if 的正确想法
猜你喜欢
  • 2012-07-28
  • 2013-04-14
  • 2020-07-09
  • 2020-02-22
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多