Директива ngHide работает только с модулем ngRoute после обновления страницы

Когда я вхожу в свое приложение, я хочу, чтобы кнопка входа в систему и регистрации исчезла с панели навигации, поэтому я использую директиву ng-hide, если вход был успешным и токен был получен с сервера, который я храню в файлах cookie.

Nav является частью файла index.html.

Поскольку я использую угловую маршрутизацию, при успешном входе в систему index.html снова не загружается, вместо этого я отображаю домашнюю страницу с помощью директивы ng-view.

Проблема в том, что я должен обновить страницу, чтобы ng-hide работал. Я предполагаю, что это потому, что ng-hide является частью страницы index.html, которая не перезагружается.

Надеюсь, что есть лучшее решение, чем обновлять страницу каждый раз, когда кто-то входит в систему.

Вот некоторые из моих соответствующих кодов.

HTML

<!-- Navigation -->
<nav class="navbar navbar-custom navbar-fixed-top" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse">
                <i class="fa fa-bars"></i>
            </button>
            <a class="navbar-brand page-scroll" href="#/">
                <i class="fa fa-play-circle"></i>  <span class="light">Webnar</span>
            </a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse navbar-right navbar-main-collapse">
            <ul class="nav navbar-nav">
                <!-- Hidden li included to remove active class from about link when scrolled up past about section -->
                <li class="hidden">
                    <a href="#page-top"></a>
                </li>
                <li>
                    <a class="page-scroll" href="#about">Webinars</a>
                </li>
                <li ng-hide="token">
                    <a class="page-scroll" href="#/login">Login</a>
                </li>
                <li ng-show="token">
                    <a class="page-scroll " href="#/create">Add a webinar</a>
                </li>
                <li ng-hide="token">
                    <a class="page-scroll btn btn-default " href="#/signup">Sign Up</a>
                </li>
                <li ng-show="token" >
                  <a class="page-scroll btn btn-default" ng-click="logOut()">Logout</a>
                </li>

            </ul>
        </div>
        <!-- /.navbar-collapse -->
    </div>
    <!-- /.container -->
</nav>

App.js

var webinarApp = angular.module('webinarApp', ['ngCookies', 'ngRoute']);

webinarApp.config(function($routeProvider){

    $routeProvider

    .when('/', {
      templateUrl: './home.html',
      controller: 'mainController'
    })
    .when('/signup', {
      templateUrl: './signup.html',
      controller: 'mainController'
    })
    .when('/login', {
      templateUrl: './login.html',
      controller: 'mainController'
    })
    .when('/create', {
      templateUrl: './create.html',
      controller: 'mainController'
    })
});

webinarApp.controller('mainController', ['$scope', '$http', '$cookies', '$location', function($scope, $http, $cookies, $location){

  $scope.welcomeMessage = '';
  $scope.users = [];
  $scope.searchQuery = "";
  $scope.orderByField = 'name';
  $scope.newUser = {};
  $scope.logInUser = {};
  $scope.webinars = [];
  $scope.newWebinar = {};
  $scope.isDisabled = false;


  // ============== Users ================

  $scope.getUsers = function(){
    $http.get('/api/users').then(function(response){
      $scope.users = response.data;
    });
  };
  $scope.getUsers();

  $scope.createUser = function(){
    $http.post('/api/users', $scope.newUser).then(function(response){
      console.log(response.data)
      $scope.users.push(response.data);
      $scope.newUser = {};
      $location.path('/login');
    });
  };

  $scope.obtainToken = function(){
    $http.post("/api/users/authentication_token", $scope.logInUser).then(function(reponse){
      $scope.token = reponse.data.token;
      console.log($scope.token);
      $cookies.put('token', $scope.token);
      $location.path('/')
    });
  };

5 ответов

Решение

Это потому, что вы поместили панель навигации на страницу индекса. Это не шаблон, который загружается модулем маршрута. Так что это не связано ни с каким маршрутом и контроллером, которые связаны с ним. Контроллер, объявленный в маршрутах, применяется только к шаблону, загруженному модулем маршрута.

Чтобы привязать контроллер к какому-либо маршруту, используйте директиву ng-controller. Поместите это на свой <nav> элемент

Обратите внимание, если вы используете синтаксис "как контроллер", который вы должны сделать в контроллере: this.isDisabled вместо $scope.isDisabled

Документация: https://docs.angularjs.org/

Если вам нужно обновить данные для этого контроллера с остальной частью приложения. Используйте $rootScope. Если вы используете синтаксис "ctrl as", это будет проще: this.$ RootScope=$rootScope;

Если вам это не нравится, используйте $watch для отслеживания изменений и привязки currentValue к контроллеру:

$rootScope.watch('myParameter', function(new){
     this.myParameter = new;
});

И НЕ ЗАБУДЬТЕ ИНИЦИАЛИЗИРОВАТЬ ПЕРЕМЕННОЕ В $ROOTSCOPE. Или переменная окажется в дочерней области, которая не будет видна контроллеру вашей панели навигации.

У меня была такая же проблема, как у ОП (видицаксена), и я решил ее так же, как и он. Как и он, я имел ng-hide в моей навигации, которая была расположена в index.html. мой ng-hides правильно работал при начальной загрузке страницы, но когда я попытался перейти к другому представлению, мой ng-hideне будет работать, пока я не обновлю страницу.

Мое решение: Точно так же, как @viditsaxena описывает в своих комментариях под принятым ответом (используйте $rootScope вместо $scope), но я решил поместить свой реальный код здесь, чтобы показать вам, как я заставил его работать в моем app.js файл:

Я пошел от этого (ng-hide требуется обновить, чтобы загрузить после того, как я ушел от первоначального представления):

app.controller('routeController', ['$scope', '$location', function($scope, $location) {
    $scope.showPortfolioHeader = $location.path() === '/jcRealty';
}]);

Для этого (теперь мои нг-шкуры не требуют обновления после того, как я ушел от своего первого вида):

app.controller('routeController', ['$rootScope', '$location', function($rootScope, $location) {
    $rootScope.showPortfolioHeader = $location.path() === '/jcRealty';
}]);

Принятый ответ дал мне часть пути, но мне было трудно расшифровать часть грамматики в его ответе. Мое собственное тестирование подтвердило кое-что из того, что он сказал. Мой контроллер выше (routeController) относится к представлению, расположенному в пути /jcRealty. Если я поставлю ng-hideв моем представлении jcRealty, они работают должным образом (обновление не требуется), используя $scope, Но так как мой ng-hideнаходятся на index.html, вне пути этого контроллера, $rootScope было необходимо, чтобы не требовать перезагрузки страницы.

Вы пытались использовать $scope.$ Apply()???

  $scope.$apply(function() {
    $scope.token = <whatever value>;
  })

Вы должны объявить $scope.token с другими объявлениями переменных. Он не существует в области видимости при первоначальной настройке ng-hide.

$scope.isDisabled = false; 
$scope.token;

Хорошо, я думаю, что один из способов сделать это - добавить контроллер для nav, скажем, navbarController.

    <nav ng-controller="navbarController">...</nav>

Inject $rootScope into both maincontroller and navbarController.

затем в mainController всякий раз, когда вам нужно изменить значение токена, сделайте это

$rootScope.$emit('tokenValueChange', <value>);

then in navbarController add,

$rootScope.$on('tokenValueChange', function(newValue) {
    $scope.token = newValue;
})

I am not sure if this is a perfect method but this should work.
Другие вопросы по тегам