如何将数据从ng-view传递到位于Agularjs中index.html的navbar

时间:2016-12-14 08:51:41

标签: javascript html angularjs twitter-bootstrap mean-stack

我刚刚开始学习MEAN堆栈,并尝试从头开始构建一个身份验证页面(尽管我知道我可以使用开箱即用的身份验证,但我这样做是为了有一个背景知识)但我发现它有点在我的导航栏上更新文本很棘手。 我的index.html看起来像这样;

<nav class="navbar navbar-default navbar-fixed-top" ng-controller="HeadController">
 <div class = "container-fluid">
  <ul class="nav navbar-nav navbar-right">
     <li><a href="#">{{user.name}}</a></li>
  </ul>
 </div>
</nav>
<div class="container" ng-view></div>

我的app.js看起来像这样;

var app = angular.module('app',['ngRoute'])
     .service("userService", function () {
         this.user = {};
         this.getUser = function () {
            return this.user;
         };
         this.setUser = function (user) {
            this.user = user;
         };
      })
      .config(['$routeProvider', function ($routeProvider) {
         $routeProvider
           .when('/login', {
               templateUrl: 'partials/login.html',
               controller: 'LoginCtrl as login'
            })
           .when('/user/profile',{
              templateUrl: 'partials/profile.html',
              controller: 'ProfileCtrl as profile'
           })
           .otherwise({
               redirectTo: '/login'
            });
      }]);
   app.controller("HeadController", [
      '$scope',
      'userService',
      function ($scope, userService) {
       $scope.user = userService.getUser();
   }]);
  app.controller("LoginCtrl", [
      "$location",
      "userFactory",
      "userService",
      function ($location, userFactory, userService) {
         var login = this;
         login.user = {
            username: '',
            password: '',
            isRemember: true
         };
         login.login = function () {
            userFactory.login(login.user)
               .success(function (user) {
                  userService.setUser(user);
                  $location.path("/user/profile");
               })
               .error(function (err) {
                  console.log(err);
               });
         };
   }]);

最后,我的userFactory.js看起来像这样;

 function login(user) {
            return $http({
               url: '/api/login/',
               method: "POST",
               data: user,
               headers: {
                  'Content-Type': 'application/json'
               }
            });
         }
return{login:login};

每当我登录时,我都希望{{user.name}}更新,但这不会发生。我不知道怎么做到这一点。我该怎么做才能实现这一目标?

1 个答案:

答案 0 :(得分:2)

问题在于userService.setUser(user)将服务器在内存中的引用替换为&#34; user&#34;上一个用户对象(以及内存中的引用)绑定到HeadController的$ scope之后的对象。解决这个问题的方法很简单:

1。使用setUser突变(而不是替换)原始对象:

this.setUser = function(newUserData) {
  angular.extend(this.user, newUserData);
};

2。动态引用&#34; name&#34;在你的模板中

<li><a href="#">{{ userService.getUser().name }}</a></li>

3。(首选IMO,虽然绝对不是最容易实现的)在您的用户服务中制作自定义事件处理程序,以便在您调用setUser时,回调&#34;听众&#34;将被调用。这样您就可以在HeadController

中执行此类操作
userService.onUserUpdate(function(newUser) {
  $scope.user = newUser; // or userService.getUser();
});

并保持模板/视图更清晰,更具声明性,就像你现在拥有它一样:

<li><a href="#">{{ user.name }}</a></li>

这可以像这样实现。在userService添加:

var privateUserUpdateListeners = [];   

this.onUserUpdate = function(cb)
  if (angular.isFunction(cb)) {
    privateUserUpdateListeners.push(cb);
    // Return a callback that can be used to deregister the listener.
    // In production code, you may want to wrap this function
    // to ensure that it may only get called once.
    return function() {
      var index = privateUserUpdateListeners.indexOf(cb);
      privateUserUpdateListeners.splice(index, 1);
    };
  }
};

this.broadcastUserUpdate = function(user) {
  privateUserUpdateListeners.forEach(function(cb) {
    cb(user);
  });
};

然后在setUser中,您可以添加如下广播:

this.setUser = function(user) {
  this.user = user;
  this.broadcastUserUpdate(user);
};

这应该可以解决问题。