更新ng-view之外的HTML元素

时间:2013-01-30 15:59:41

标签: javascript angularjs

我在页面上有以下HTML:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="myCart">
<head>
    <title>AngularJS Shopping Cart</title>
    <link href="css/jsonstore.css" rel="stylesheet" />
</head>
<body>
    <div id="container">
        <div id="header">
            <h1>The JSON Store</h1>
            <div class="cart-info">
                My Cart (<span class="cart-items">{{item.basketCount}}</span> items)
            </div>
        </div>
        <div id="main" ng-view>
        </div>
    </div>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular-resource.js"></script>
    <script src="js/routing.js"></script>
    <script src="js/dataresource.js"></script>
    <script src="js/basketinfo.js"></script>
    <script src="js/index.js"></script>
    <script src="js/detail.js"></script>
</body>
</html>

我的路线将div“main”替换为HTML模板,但我想用购物篮计数来更新标题部分。

我已经尝试过模型绑定它,如HTML和下面所示:

function DetailController($scope, item, basketDetail) {
    $scope.item = item;
    $scope.item.basketCount = basketDetail.getCount();

    //more code
}

我也尝试过注入服务并从HTML中调用它。两种方式都没有做任何事情。

有人可以帮忙吗?

由于

3 个答案:

答案 0 :(得分:15)

您的header div实际上是一个视图,就像您定义的用于ng-view的其他视图一样。有一天,您可能希望在该标题视图中显示的不仅仅是一个basketCount模型。但是,您甚至将一个模型数据投影到该标题部分这一事实使该部分成为一个视图。因此,我建议给它自己的$ scope来投射该模型,因此它自己的控制器。

那么剩下的是放置basketCount模型的位置?我们必须考虑多个视图可能允许用户做一些需要影响该模型的事情。 Angular对“许多需要访问”的正常回答是依赖注入。所以,我会将basketCount模型放入服务中。需要访问它的视图/控制器可以注入它。有一天,您的应用可能会有其他不需要访问这些模型的视图,因此这些视图不会注入服务。

潜在地,整个篮子可以在这项服务中建模:

app.factory('basketService', function() {
   return {
     items: [],
     itemCount: 0,
     ...
   }
});


function HeaderCtrl($scope, basketService) {
   $scope.basket = basketService;
   ...
}

function DetailCtrl($scope, basketService) {
   $scope.basket = basketService;
   ...
}

<div id="header" ng-controller="HeaderCtrl">
   <h1>The JSON Store</h1>
   <div class="cart-info">
        My Cart (<span class="cart-items">{{basket.itemCount}}</span> items)
   </div>

答案 1 :(得分:3)

你需要注入$ rootScope,然后更新它:

function DetailController($scope, $rootScope, basketDetail) {
    $rootScope.item = $rootScope.item || {};
    $rootScope.item.basketCount = basketDetail.getCount();

    //more code
}

还有很多方法可以做到这一点,但这是我的第一个建议,因为它可能是最简单的。


编辑:根据您的要求,其他方式执行此操作...

您可以使用$ parent推送到您的父范围。好处是它非常快速和干净......不利的一点是,你的一个控制器在某种程度上假设它的父母是什么(但这仍然不是很糟糕,真的),这有点草率:

   {{item.basketCount}}
   <div ng-controller="InnerCtrl">
   </div>


function InnerCtrl($scope, basketDetail) {
   $scope.$parent.item = $scope.$parent.item || {};
   $scope.$parent.item.basketCount = basketDetail.getCount();
}

然后是上面提到的@asgoth方法,您可以在父作用域上使用嵌套控制器和方法来更新父作用域。有效,但就像我在“其他方法”部分中的其他解决方案一样,它依赖于对控制器容器的假设,它还依赖于您创建一个额外的控制器。

最后,您可以创建一项服务。现在服务通常不会以这种方式使用,但您可以使用这种方式。您可以在哪里获取basketDetail服务,并使用它来回传递值。像这样:

app.factory('basketDetail', function() {
   return {
      items: { basketCount: 0 },
      getCount: function() {
          //return something here
          return 123;
      }
   }
});


function FooCtrl($scope, basketDetail) {
   $scope.items = basketDetail.items;
   $scope.items.basketCount = basketDetail.getCount();
}

function BarCtrl($scope, basketDetail) {
   $scope.items = basketDetail.items;
}


<div ng-controller="FooCtrl">
  {{items.basketCount}}
</div>
<div ng-controller="BarCtrl">
  {{items.basketCount}}
</div>

这是有效的,因为两个控制器中的$ scope保持对同一对象的引用,该对象由basketDetail服务维护。但同样,这不是推荐的方式。

所有这些都说: $ rootScope,IMO最有可能是您正在寻找的。

  • 不需要创建额外的控制器。
  • 不需要创建任何其他函数引用。
  • 不会导致创建任何其他父/子范围嵌套和后续监视。

答案 2 :(得分:2)

不需要$rootScope。使用其范围内的函数创建父控制器(例如RootController)。子范围将自动继承它:

<div id="container" ng-controller="RootController">
...


function RootController($scope) {
   $scope.item = {};

   $scope.setBasketCount = function (detail) {
      $scope.item.basketCount = detail.getCount();
   }
}

在您的详细控制器中,您只需使用setBasketCount()功能:

function DetailController($scope, item, basketDetail) {
    $scope.item = item;
    $scope.setBasketCount(basketDetail);

    //more code
}