仅在定义$ scope.myVar后才渲染AngularJS指令

Don*_*n P 7 angularjs angularjs-directive angularjs-scope

加载我的AngularJS"页面"时,我从服务器获取一些数据并将其设置为范围:

myApp.controller('somePage', ['$scope', 'User', '$routeParams', function($scope, User, $routeParams){

  // Get the user.
  User.get('1234').then(function(user){
    $scope.user = user;
  });

});
Run Code Online (Sandbox Code Playgroud)

在我的页面上,我有一个需要$scope.user定义的指令.

<div>
  <user-profile-info></user-profile-info>
</div>
Run Code Online (Sandbox Code Playgroud)

指令:

myApp.directive('addActionButton', function() {
  return {
    scope: false,
    link: function(scope, element, attrs){
      element.bind('click', function(){
        alert(scope.user.name);
      });
    },
    template: '<button id="foo">Say hi to {{ user.name }}</button>'
  };
})
Run Code Online (Sandbox Code Playgroud)

现在,页面在$scope.user定义之前呈现组件,因此存在错误.

如何使该指令仅在$scope.user存在时呈现?或者,一旦控制器完成数据获取后,如何才能使我的页面视图呈现?

编辑:所有上述代码都大大简化,因此您不必阅读额外信息 - 但仍然具有组件所需的约束(例如链接,带有属性的模板,带有ajax调用的范围).

Sho*_*omz 8

ng-if的意思是:

<user-profile-info ng-if="user"></user-profile-info>
Run Code Online (Sandbox Code Playgroud)

看这个例子:


angular.module('myApp', [])
.controller('somePage', ['$scope', '$timeout', function($scope, $timeout){

  // Get the user
  // simulating delayed request, 3 secs
  $timeout(function(){
    $scope.user = {
      name: 'Shomz'
    };
  }, 3000);
  

}])
.directive('userProfileInfo', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs){
      element.bind('click', function(){
        alert(scope.user.name);
      });
      alert(scope.user.name); // this would throw an error without ng-if
    },
    template: '<button id="foo">Say hi to {{ user.name }}</button>'
  };
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="somePage">
  <p ng-hide="user">Waiting for user data...</p>
  <user-profile-info ng-if="user">qwe</user-profile-info>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 只是`ng-if ="user && question"`应该这样做.是的,一切都很好. (2认同)

PSL*_*PSL 3

我认为您更担心指令内部的处理过早,而不是指令的渲染。您可以设置 2 路绑定并附加承诺,或者您可以使用事件来让指令知道开始,或者您可以在初始化指令过程之前对数据设置一次性监视。所以基本思想是不要直接在指令链接函数中编写处理代码。另外,最好有一个与指令关联的控制器,并在获得数据后触发指令控制器中的 init 函数。

一个包含一次性方法和承诺方法的简单示例。

.directive('userProfileInfo', function($q){
   return{
     /*Your configuration*/,
     scope:{user:"="},
     link: function linker(scope, elm, attrs){
        /*
         Promise way
        */
         //Set up data or promise, q.when will make sure it is always a promise, be careful about not setting values like null etc..
         $q.when(scope.user).then(init);
        /*
          One time watch way
        */
        var unwatch = scope.$watch('user', function(user){
             if(angular.isDefined(user)){
                 unwatch(); //Remove the watch
                 init(); //initialize
             }
        });
        function init(){
           //Initialize directive processing accessing scope.user
        }
     }
   }
});
Run Code Online (Sandbox Code Playgroud)

并将其绑定为:

<user-profile-info user="user"></user-profile-info>
Run Code Online (Sandbox Code Playgroud)

如果您使用一次性手表,如果使用 Promise 方法,请保持代码不变。绑定承诺,即

在你的控制器中:

 $scope.userPromise = User.get('1234');
Run Code Online (Sandbox Code Playgroud)

 <user-profile-info user="userPromise"></user-profile-info>
Run Code Online (Sandbox Code Playgroud)

如果您担心根本不渲染指令,只需ng-if在指令元素上使用,只要您的指令优先级小于 ng-ifs,它就不会渲染。