【问题标题】:Why does ng-if only work with ng-click if they are in the same element?为什么 ng-if 仅适用于 ng-click 如果它们在同一个元素中?
【发布时间】:2016-12-22 03:22:04
【问题描述】:

我根据用户是否登录或退出来隐藏和显示导航栏元素。

在主控制器中:

    $scope.FBlogin = function(){
    FB.login(function(response) {
        if (response.authResponse) {
         console.log('Welcome!  Fetching your information.... ');
         FB.api('/me', function(response) {
           console.log('Good to see you, ' + response.name + '.');
           $cookies.put('userObj', response);

           var accessToken = FB.getAuthResponse().accessToken;
           console.log(accessToken);
           authFact.setAccessToken(accessToken);
           console.log(response);

            $scope.out=true;
            $scope.in = false;
            $scope.feed = true;

            $location.path("/myFeed");
            $scope.$apply();

         });
        } else {
         console.log('User cancelled login or did not fully authorize.');
        }
    });


};

    $scope.FBlogout = function(){
        $scope.out = false;
        $scope.in = true;
        $scope.feed = false;
        $cookies.remove("userObj");
        $cookies.remove('accessToken');
        $location.path("/");
        $scope.$apply();

};


}]);

当从列表项调用登录函数时,它在这里起作用。登录链接消失,退出链接显示。

导航指令(主控制器的一部分)

<li ng-click="FBlogin()" ng-if="in"><a href="#login">Login</a></li>
<li ng-if="feed"><a href="#myFeed">My Feed</a></li>
<li id="logout" ng-click="FBlogout()" ng-if="out"><a>Logout</a></li>

angular.module('dsnApp')
.directive('navApp', function(){
  return{
    templateUrl: 'templates/nav.html',
    controller:'mainController',
    replace: 'true'
  }
});

但是当这个按钮调用登录功能时,登录按钮并没有消失,也没有显示注销。

登录指令(主控制器的一部分)

<div class="fbLogin" ng-controller="mainController">
    <h1 style="display: inline-block">Login with <span id="facebook">facebook</span></h1><br>
    <button ng-click="FBlogin()">Login</button>
</div>

    app.config(function($routeProvider) {
$routeProvider

    // route for the home page
    .when('/', {
        templateUrl : 'templates/home.html',
        controller  : 'mainController'
    })
    // route for the about page
    .when('/explore', {
        templateUrl : 'templates/explore.html',
        controller  : 'exploreController'
    })

    // route for the service page
    .when('/login', {
        templateUrl : 'templates/login.html',
        controller  : 'mainController'
    })

     // route for the about page
    .when('/myFeed', {
        templateUrl : 'templates/myFeed.html',
        controller  : 'feedController',
        authenticated : true
    })

    .otherwise('/', {
        templateUrl : 'templates/home.html',
        controller  : 'mainController'
    });

});

这是否与范围有关?

【问题讨论】:

  • div &lt;div class="fbLogin" ng-controller="mainController"&gt; 似乎没有loginlogout 链接。你有一个单独的 div 和导航指令的单独控制器实例吗?
  • 你使用指令吗?我的意思是这样的:app.directive('loginDirective')?
  • 您可以使用 $rootScope.in 和 $rootScope.out。
  • @ManojLodhi:当然可以,但正如 Angular 常见问题解答所述(docs.angularjs.org/misc/faq)“当然,全局状态很糟糕,您应该谨慎使用 $rootScope
  • 来自docs.angularjs.org/misc/faq "如果你想在 $rootScope 上放置一个函数,最好把它放在一个可以在需要的地方注入的服务中,并且更容易测试。相反地,不要创建一个生活中唯一目的是存储和返回数据位的服务。”

标签: javascript html angularjs


【解决方案1】:

这显然与您的scope 有关。 $scope.in 必须与 $scope.FBLogin()$scope.FBlogout() 具有相同的范围。

既然你说你正在使用导航指令,我猜你有:

  1. 导航列表的指令,因此您在此列表中的链接有效
  2. 另一个登录指令,
  3. 和一个控制器(mainController)

虽然它们都有相同的$scope 作为它们的依赖注入器,但它们的内容并不相同。

要实现您想要做的事情,您必须共享一个变量来控制导航栏在您的应用中的可见性(控制器和指令)。下面是如何做到这一点,下面是一个工作示例

 // angular app.js
 var app = angular.module('app', []);

 // main controller
 app.controller('MainController', function($scope, navbarState) {
     $scope.hide = function(){
        navbarState.hideNavbar(); // executes this when logout
     }
 });

 // navbar directive which use navbarState service
 // to show navbar, we use `ng-if` (see template)
 app.directive('navbarDirective', function(){
   return {
    restrict: 'EA',
    template: "<div ng-if=\"navbarState.currentState == 'show'\"></div>",
    controller: function ($scope, navbarState) {
      $scope.navbarState = navbarState;
    }
   }
 });

 // navbarState is a service that is shared across 
 // directives and controllers in your app.
 // this service holds a value (currentState) which indicates
 // navbar when to show or hide
 app.service('navbarState', function($window) {
    this.currentState = "show";
    this.showNavbar = function(){
       this.currentState = "show";
    }
    this.hideNavbar = function(){
       this.currentState = "hide";
    }
 });

请参阅此 plunkr 示例以获得详细答案:https://plnkr.co/edit/LCS4NxJwcbfeVAXgLKJ8?p=preview

【讨论】:

  • 我添加了导航指令。登录没有指令,它是一条路线。我在最初的帖子中添加了更多代码。
  • 您的代码不起作用,因为您尝试使用 $scope.in 这是局部变量,并且仅在指令范围内可用。有一些方法,比如service 来规避这个问题,我会尽快重写我的答案。
  • @OliviaOddo:添加一个工作样本。希望这是你需要的
【解决方案2】:

这是否与范围有关?

是的,它与范围有很大关系。

<body ng-controller="mainController">
  <div>
      <ul class="nav">
       <li id="home"><h1><a href="#/">Do Something Nice</a></h1></li>
       <li><a href="#explore">Explore</a></li>
       <li><a href="#login">Login</a></li>
       <li><a href="#myFeed">My Feed</a></li>
       <li id="logout" ng-click="FBlogout()">   <a>Logout</a></li>
    </ul>
  </div>
   <!-- this is where content will be injected -->
   <div id="main">

<!-- angular templating -->
<!-- this is where content will be injected -->
<div ng-view></div>

应用程序主体有一个ng-controller 指令,该指令创建一个子作用域并注入mainController

ng-view 指令正在创建另一个子作用域,并且路由正在该作用域上实例化另一个 mainController

此外,ng-if 指令正在创建另一个子作用域。

更糟糕的是,自定义 dsn-app 指令正在实例化另一个 mainController

要了解范围,我建议阅读:

【讨论】:

    猜你喜欢
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    • 2015-09-01
    • 2012-08-07
    • 2014-07-16
    • 2023-03-07
    相关资源
    最近更新 更多