如何在元素指令上使用ng-if来有条件地调用模块

时间:2016-11-03 21:14:25

标签: javascript angularjs angular-directive angular-ng-if

我有一组标签作为模块标签,它们必须是彼此的兄弟姐妹和主视图容器的第一个子节点。

如果用户通过身份验证,我想互相调用前两个。

我可以验证范围内是否有isAuthenticated,但我所拥有的条件没有得到遵守。此外,出于性能原因,我还想避免调用整个隐藏模块。

我做错了什么以及包含一组模块标签的最佳条件是什么?

<sol-tabs id="main-vifirstew" data-loggedin="{{isAuthenticated}}" selected="{{defaultTab}}">
    <dashboard-pane
        ng-if="isAuthenticated == true"
        <!--ng-show="isAuthenticated == true"
        ng-hide="isAuthenticated == false" i've tried all these directives and none work -->
        tab-icon="ambiance" ></dashboard-pane>
    <user-login
        ng-if="isAuthenticated == false"
        <!--ng-hide="isAuthenticated == true"
        ng-show="isAuthenticated == false"-->
        tab-icon="login" ></user-login>            
    <third-pane tab-icon="search"></third-pane>
    <fourth-pane tab-icon="list-ol"></fourth-pane>
</sol-tabs>

用户登录模块:

import 'angular';

var app = angular.module('user-login', ['sol-backend', 'services'])
.constant('AUTH_EVENTS', {
  loginSuccess: 'auth-login-success',
  loginFailed: 'auth-login-failed',
  logoutSuccess: 'auth-logout-success',
  sessionTimeout: 'auth-session-timeout',
  notAuthenticated: 'auth-not-authenticated',
  notAuthorized: 'auth-not-authorized'
})
.constant('USER_ROLES', {
  all: '*',
  admin: 'admin',
  editor: 'editor',
  guest: 'guest'
})
.directive('userLogin',
        ['$rootScope', '$window', '$timeout', '$http', '$location', 'solBackend', 'AUTH_EVENTS', 'USER_ROLES',
        ($rootScope, $window, $timeout, $http, $location, solBackend, AuthService, AUTH_EVENTS, USER_ROLES) => {
  return {
    restrict: 'E',
    templateUrl: '/modules/user-login/user-login.html',
    replace: true,
    scope: true,
    link: function ($scope, element, attrs) {
      console.log('userLogin Directive: ', AUTH_EVENTS, $scope.isAuthenticated);

        $scope.currentUser = false;
        $scope.isAuthenticated = false;

        $rootScope.currentUser = false;
        $rootScope.isAuthenticated = false;

      var cookie = false;
      var value = "; " + document.cookie;
      var parts = value.split("; " + 'tacsession' + "=");
      if (parts.length == 2) cookie = parts.pop().split(";").shift();
      console.log('cookie', cookie);
      if (cookie.length > 10) {
          $http.get('https://localhost.trackauthoritymusic.com/json/getme')
          .then(function(res) {
              if (res.data.error) {
                  console.log('tacsession failed', res.data.error);
              } else if (res.data.user_id) {
                  $scope.setCurrentUser(res.data);
              }
          }, 
            function(response) { // optional
                console.log('cookie rejected', response);
          });
      }
      // /json/getme > IF VALID set, ELSE reject 
      $scope.toggleGoogleAuth = () => {
          if (!$scope.authenticated)
              solBackend.authenticateWithPopup();
          else
              solBackend.unauthenticate();
      };

      solBackend.getAuth().then(($auth) => {
          $auth.$onAuth((auth) => {
              if (auth && auth.uid) {
                  $scope.authenticated = true;
                  $scope.authData = auth.google;
              }
              else {
                  $scope.authenticated = false;
              }
          });
      });
    }
  };
}])
.factory('AuthService', function ($http, Session) {
  var authService = {};

  authService.login = function (credentials) {


      function serializeParams(obj) {
        var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

        for(name in obj) {
          value = obj[name];

          if(value instanceof Array) {
            for(i=0; i<value.length; ++i) {
              subValue = value[i];
              fullSubName = name + '[' + i + ']';
              innerObj = {};
              innerObj[fullSubName] = subValue;
              query += param(innerObj) + '&';
            }
          }
          else if(value instanceof Object) {
            for(subName in value) {
              subValue = value[subName];
              fullSubName = name + '[' + subName + ']';
              innerObj = {};
              innerObj[fullSubName] = subValue;
              query += param(innerObj) + '&';
            }
          }
          else if(value !== undefined && value !== null)
            query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
        }

        return query.length ? query.substr(0, query.length - 1) : query;
      };
    return $http({
        url: 'https://localhost.trackauthoritymusic.com/manage/users/login?tar=doAjax',
        method: "POST",
        dataType: 'json',
        data: serializeParams(credentials)
    })
    .then(function(res) {
            Session.create(res.data);
            return res.data;
        }, 
        function(response) { // optional
            console.log(response);
        });
  };

  authService.isAuthenticated = function () {
    console.log('checking isAuthenticated', Session);
    return Session.user_id < 1;
  };

  authService.isAuthorized = function (role) {
    console.log('question isAuthorized: ' + role, USER_ROLES);
    return (authService.isAuthenticated() && typeof USER_ROLES[role] == 'object' && USER_ROLES[role] > 2);
  };
  return authService;
})
.factory('AuthResolver', function ($q, $rootScope, $state) {
  return {
    resolve: function () {
      var deferred = $q.defer();
      var unwatch = $rootScope.$watch('currentUser', function (currentUser) {
        console.log('watching currentUser ', currentUser);
        if (angular.isDefined(currentUser)) {
          if (currentUser) {
            console.log('currentUser defined');
            deferred.resolve(currentUser);
          } else {
            deferred.reject();
            $state.go('user-login');
          }
          unwatch();
        }
      });
      return deferred.promise;
    }
  };
})
.service('Session', function () {
  this.create = function (me) {
    this.me = me;
    this.user_id = parseInt(me.user_id);
    this.user_status = parseInt(me.user_status);
  };
  this.destroy = function () {
    this.me = null;
    this.user_id = -1;
    this.user_status = 0;
  };
})
.controller('LoginController', function ($scope, $rootScope, AUTH_EVENTS, AuthService) {
      console.log('LoginController: ', AUTH_EVENTS);
      $scope.credentials = {
        user_email: '',
        password: ''
      };
      $scope.login = function (credentials) {
        console.log('Sending credentials: ', $scope.credentials);
        AuthService.login(credentials).then(function (user) {
          $rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
          $scope.setCurrentUser(user);
        }, function () {
          $rootScope.$broadcast(AUTH_EVENTS.loginFailed);
        });
      };
})
.config(function ($httpProvider) {
  $httpProvider.interceptors.push([
        '$injector',
        function ($injector) {
          return $injector.get('AuthInterceptor');
        }
      ]);
})
.factory('AuthInterceptor', function ($rootScope, $q, AUTH_EVENTS) {
  return {
    responseError: function (response) { 
      $rootScope.$broadcast({
        401: AUTH_EVENTS.notAuthenticated,
        403: AUTH_EVENTS.notAuthorized,
        419: AUTH_EVENTS.sessionTimeout,
        440: AUTH_EVENTS.sessionTimeout
      }[response.status], response);
      return $q.reject(response);
    }
  };
});

app.run(function ($rootScope, AUTH_EVENTS, AuthService) {
  console.log('RUNNING USER-LOGIN: ', AUTH_EVENTS);
  $rootScope.$on('$stateChangeStart', function (event, next) {
    console.log('state change start', next.data);
    if (!AuthService.isAuthenticated()) {
      event.preventDefault();
      console.log('NOT AUTHENTICATED: ' + AUTH_EVENTS.notAuthenticated);
      $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
    }
  });
});


export default app;

ambiane-pane模块:

import 'angular';

export default angular.module('ambiance-pane', 
        ['sol-backend', 'services', 'filters'])
        .directive('ambiancePane',
            ['$rootScope', '$window', '$timeout', '$http', '$location', 'youtubeAPI', 'taAPI', 'playList', 'solBackend',
            ($rootScope, $window, $timeout, $http, $location, youtubeAPI, taAPI, playList, solBackend) => {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: '/modules/ambiance-pane/ambiance-pane.html',
        scope: {},
        link: ($scope, $element) => {
            console.log("AMBIANCE LINKED playList.playlist", playList.playlist, $scope.isAuthenticated);
            Object.assign($scope, {
                challenge_id:null,
                active: false,
                status: 'active',
                users_count:0,
                track_scount:0,
                challenge_id:-1,
                track_list:[],
                track_order:{},
                author_id:-1,
                ta_id:-1
            });
        }, 
        controller: function($scope, $element, $attrs) {
            $scope.challenges = [{challenge_id:-1,challenge_title:"My custom playlist",group_id:-1}];
            $scope.challenge = null;
            $scope.selectedChallengeItem = [0];
            $scope.currentUser = false;
            $scope.isAuthenticated = false;

            var cid = playList.getNowPlayingIdx();
            var state = playList.getState();

            console.log('ambiance-pane knows isAuthenticated', $scope.isAuthenticated);
            if (true || $scope.isAuthenticated) {

                taAPI.getChallenges().then(function(response) {
                    if (typeof response.popBody == 'object') {
                        console.log('ALL CHALLENGES: ', response);
                        var options = response.popBody;
                        options['_-1'] = {challenge_id:-1,challenge_title:"My custom playlist",group_id:-1};
                        $scope.challenges = options;

                        for(var i in response.popBody) {
                            $scope.selectedChallengeItem = response.popBody[i];
                            break;
                        }


                        if ($scope.selectedChallengeItem.challenge_id > 0) {
                            var cid = $scope.selectedChallengeItem.challenge_id;
                            taAPI.getTAplaylist(cid).then(function(response) {
                                console.log('GOT CHALLENGE: ', response);
                                $scope.challenge = response.popBody;
                            });
                        }

                    }
                });
            }

            $scope.items = playList.playlist;
            $scope.$watch(() => playList.metadata, (newVal, oldVal) => {
                if (!!newVal) {
                    newVal.$bindTo($scope, "metadata");
                } else {
                    $scope.metadata = null;
                }

                if (oldVal) {
                    oldVal.$destroy();
                }
            });

            $scope.getChallenge = function(){
                return $scope.challenge;
            }               
        }
    }
}])
.directive('challengeBlock', function ($compile) {
    var definitions = {
            restrict: 'E',
            templateUrl: '/html/playlist/challengeBlock.html',
            replace: true,
            scope: true,
            transclude:true,
            link: function($scope, $element, $attrs) {
                $scope.dataSources = {
                    ci: 'https://localhost.trackauthoritymusic.com',
                    angular: 'https://localplayer.trackauthoritymusic.com',
                    api : 'https://localhost.trackauthoritymusic.com'
                }
            }
        };
        return definitions;
    });

调用所有其他人的应用程序模块:

[import '...whole project'];

const cacheUpdated = new Promise((resolve, reject) => {
    if (window.hasOwnProperty('applicationCache')) {
        window.applicationCache.addEventListener('updateready', function() {
            resolve();
        });
    }
});

export default angular.module('Application', [..references..]).constant('DATA_SOURCES', {
    ci: 'https://localhost.trackauthoritymusic.com',
    angular: 'https://localplayer.trackauthoritymusic.com',
    api : 'https://localhost.trackauthoritymusic.com'
}).directive('solarizdApp', ['$rootScope', 'ApiKey', 'playList', 'solBackend', function($rootScope, ApiKey, playList, solBackend) {
    return {
        restrict: 'E',
        templateUrl: '/html/app.html',
        replace: true,
        scope: true,
        link: function($scope, $element) {
            $scope.currentUser = false;
            $scope.isAuthenticated = false;

            //$rootScope.currentUser = false; // doesn't help
            //$rootScope.isAuthenticated = false;

            $scope.setCurrentUser = function (user) {
                console.log("setting global user", user);
                $scope.currentUser = user;
                if (user.user_id > 0) {
                    $scope.isAuthenticated = user.group_user_status;
                }
            };

            ApiKey.fetchKeys().then(function() {
                $element[0].classList.add('loaded');
            });

            // Notify users when there's a new version
            cacheUpdated.then(() => {
                $rootScope.$broadcast('toast::notify', {
                    text: 'Reload this app to get a newer version',
                    persist: true
                });
            });
        }, 
        controller : function($scope, $rootScope) {
            console.log('solarizdApp controller');
            $scope.currentUser = false;
            $scope.isAuthenticated = false;
            $scope.setCurrentUser = function (user) {
                console.log("setting global user from controller", user);
                $scope.currentUser = user;
                if (user.user_id > 0) {
                    $scope.isAuthenticated = user.group_user_status;
                }
            };
        }
    };
}])
.config(["$httpProvider", function($httpProvider) {
    $httpProvider.interceptors.push('middleware');
}]).factory('middleware', function() {
    return {
        request: function(config) {
            if (config.url.indexOf("trackauthoritymusic.com") > -1) {
                console.log("HTTP REQUEST", config);
                if (!config.headers || typeof config.headers != 'object') {
                    console.log('instantiating headers???');
                    config.headers = {};
                }
                config.withCredentials = true;
                config.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
            }
            return config;
        }
    };
});

2 个答案:

答案 0 :(得分:1)

您可以在所有三个模块标签中执行此操作,这将产生类似的解决方案。

可能的方法:

单独使用 ng-if 作为

<sol-tabs id="main-vifirstew" data-loggedin="{{isAuthenticated}}" selected="{{defaultTab}}">
    <dashboard-pane
        ng-if="isAuthenticated"
        tab-icon="ambiance" ></dashboard-pane>
    <user-login
        ng-if="isAuthenticated"
        tab-icon="login" ></user-login>            
    <third-pane tab-icon="search"></third-pane>
    <fourth-pane tab-icon="list-ol"></fourth-pane>
</sol-tabs>

单独使用ng-show

<sol-tabs id="main-vifirstew" data-loggedin="{{isAuthenticated}}" selected="{{defaultTab}}">
    <dashboard-pane
        ng-show="isAuthenticated"
        tab-icon="ambiance" ></dashboard-pane>
    <user-login
        ng-show="isAuthenticated"
        tab-icon="login" ></user-login>            
    <third-pane tab-icon="search"></third-pane>
    <fourth-pane tab-icon="list-ol"></fourth-pane>
</sol-tabs>

最后,使用ng-hide

<sol-tabs id="main-vifirstew" data-loggedin="{{isAuthenticated}}" selected="{{defaultTab}}">
    <dashboard-pane
        ng-show="isAuthenticated"
        tab-icon="ambiance" ></dashboard-pane>
    <user-login
        ng-show="isAuthenticated"
        tab-icon="login" ></user-login>            
    <third-pane tab-icon="search"></third-pane>
    <fourth-pane tab-icon="list-ol"></fourth-pane>
</sol-tabs>

最佳实践

使用 ng-if

<强>为什么吗

  • 只有满足条件才会检索特定元素,因此您的浏览器可能不会在开发人员工具中显示标记

  • 如果元素包含某些数据,则仅在满足条件时才加载的图像

希望这会对你有所帮助。

答案 1 :(得分:0)

我会将sol-tabs标记的内容移到指令的模板中,并将其结构如下:

<div ng-if="isAuthenticated">
    <dashboard-pane tab-icon="ambiance"></dashboard-pane>
</div>
<div ng-if="isAuthenticated">
    <user-login tab-icon="login" ></user-login>
</div>            

...

因此ng-if指令不在自定义指令上。

从我所看到的情况来看,直接在自定义指令标签中使用ng-if或ng-show会使其表现得很奇怪,我猜是因为范围。

然后在主视图中使用sol-tabs这样的内容:

<sol-tabs id="main-vifirstew" is-authenticated="isAuthenticated" data-loggedin="{{isAuthenticated}}" selected="{{defaultTab}}"></sol-tabs>