更新ng-view之外的HTML元素

时间:2021-08-07 12:21:57

I have the below HTML on a page:

我在一个页面上有下面的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>

The div "main" gets replaced by HTML templates by my routes however I would like to update the header section with a shopping basket count.

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

I have tried model binding it as shown in the HTML and below:

我尝试了模型绑定,如HTML和下面所示:

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

    //more code
}

I've also tried just injecting the service and calling it from the HTML. Both ways do not do anything.

我还尝试了注入服务并从HTML中调用它。两种方法都不起作用。

Can someone help please?

有人能帮吗?

Thanks

谢谢

3 个解决方案

#1


15  

Your header div is really a view, just like the other views you've defined for use with ng-view. Someday, you might want to show more than just a basketCount model in that header view. But the fact that you are projecting even one piece of model data into that header section makes that section a view. So, I would recommend that be given its own $scope to project that model, hence its own controller.

您的header div实际上是一个视图,就像您定义用于与ng-view一起使用的其他视图一样。有一天,您可能想要在这个标题视图中显示的不仅仅是一个篮球数模型。但事实上,你只是将一个模型数据投影到标题部分,这就使得这个部分成为了一个视图。因此,我建议给这个模型一个自己的$范围,因此它有自己的控制器。

What remains then is where to put the basketCount model? And we must consider that multiple views may allow the user to do something that need to affect that model. Angular's normal answer for "many need access" is dependency injection. So, I would put the basketCount model into a service. Views/controllers that need access to it can inject it. Someday your app may have additional views that don't need access to these models, so those views would not inject the service.

那么剩下的就是把篮球计数模型放在哪里?我们必须考虑到,多个视图可能允许用户做一些需要影响模型的事情。“许多需要访问”的正常答案是依赖注入。所以,我要把篮球模型变成一项服务。需要访问它的视图/控制器可以注入它。有一天,你的应用程序可能会有不需要访问这些模型的附加视图,所以这些视图不会注入服务。

Potentially, the entire basket could be modeled in this service:

可能,整个篮子可以在这个服务中建模:

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>

#2


3  

You'll need to inject $rootScope, then update it:

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

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

    //more code
}

There are a lot more ways to do this, but this is my first suggestion, because it's probably the easiest.

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


EDIT: per your request, other ways to do this...

编辑:根据您的要求,其他方法……

You could use $parent to push to your parent scope. The upside is it's pretty quick and clean... the downside is it's a little sloppy in that one of your controllers makes assumptions about what it's parent is to some degree (but that's still not terrible, really):

可以使用$parent将其推到父范围。好处是它非常快而且干净……缺点是你的一个控制器在某种程度上对它的父类做了一些假设,这有点草率(但这还不算太糟,真的):

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


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

Then there's the method @asgoth mentioned above where you use nested controller and a method on the parent scope to update the parent scope. Valid, but like my other solution in this "other ways to do it" section, it relies on assumptions made about the controller's container, and it also relies on you creating an additional controller.

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

Finally, you could create a service. Now services aren't generally used this way, but you could use one this way.. Where you could take your basketDetail service, and use it to pass the value back and forth. Like so:

最后,您可以创建一个服务。现在,服务通常不以这种方式使用,但是您可以用这种方式使用服务。你可以带着你的篮球细节服务,用它来来回传递价值。像这样:

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>

This works because the $scope in both controllers is keeping a reference to the same object, which is maintained by your basketDetail service. But again, this isn't really the recommended way.

这之所以有效,是因为这两个控制器中的$scope都保存了对同一对象的引用,而该对象是由篮球细节服务维护的。但是,这并不是推荐的方法。

All of that said: $rootScope, IMO is most likely what you're looking for.

所有这些都说:$rootScope, IMO很可能是你想要的。

  • It doesn't require the creation of an additional controller.
  • 它不需要创建额外的控制器。
  • It doesn't require the creation of any additional function references.
  • 它不需要创建任何其他函数引用。
  • Will not cause the creation of any additional parent/child Scope nesting and subsequent watches.
  • 不会导致创建任何其他父/子范围嵌套和后续监视。

#3


2  

No real need for $rootScope. Create a parent controller (e.g. RootController) with a function on its scope. The child scopes will automatically inherit it:

根本不需要$rootScope。创建具有作用域上的函数的父控制器(例如RootController)。子作用域将自动继承它:

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


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

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

In your detail controller you just use the setBasketCount() function:

在细节控制器中,只需使用setBasketCount()函数:

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

    //more code
}

#1


15  

Your header div is really a view, just like the other views you've defined for use with ng-view. Someday, you might want to show more than just a basketCount model in that header view. But the fact that you are projecting even one piece of model data into that header section makes that section a view. So, I would recommend that be given its own $scope to project that model, hence its own controller.

您的header div实际上是一个视图,就像您定义用于与ng-view一起使用的其他视图一样。有一天,您可能想要在这个标题视图中显示的不仅仅是一个篮球数模型。但事实上,你只是将一个模型数据投影到标题部分,这就使得这个部分成为了一个视图。因此,我建议给这个模型一个自己的$范围,因此它有自己的控制器。

What remains then is where to put the basketCount model? And we must consider that multiple views may allow the user to do something that need to affect that model. Angular's normal answer for "many need access" is dependency injection. So, I would put the basketCount model into a service. Views/controllers that need access to it can inject it. Someday your app may have additional views that don't need access to these models, so those views would not inject the service.

那么剩下的就是把篮球计数模型放在哪里?我们必须考虑到,多个视图可能允许用户做一些需要影响模型的事情。“许多需要访问”的正常答案是依赖注入。所以,我要把篮球模型变成一项服务。需要访问它的视图/控制器可以注入它。有一天,你的应用程序可能会有不需要访问这些模型的附加视图,所以这些视图不会注入服务。

Potentially, the entire basket could be modeled in this service:

可能,整个篮子可以在这个服务中建模:

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>

#2


3  

You'll need to inject $rootScope, then update it:

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

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

    //more code
}

There are a lot more ways to do this, but this is my first suggestion, because it's probably the easiest.

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


EDIT: per your request, other ways to do this...

编辑:根据您的要求,其他方法……

You could use $parent to push to your parent scope. The upside is it's pretty quick and clean... the downside is it's a little sloppy in that one of your controllers makes assumptions about what it's parent is to some degree (but that's still not terrible, really):

可以使用$parent将其推到父范围。好处是它非常快而且干净……缺点是你的一个控制器在某种程度上对它的父类做了一些假设,这有点草率(但这还不算太糟,真的):

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


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

Then there's the method @asgoth mentioned above where you use nested controller and a method on the parent scope to update the parent scope. Valid, but like my other solution in this "other ways to do it" section, it relies on assumptions made about the controller's container, and it also relies on you creating an additional controller.

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

Finally, you could create a service. Now services aren't generally used this way, but you could use one this way.. Where you could take your basketDetail service, and use it to pass the value back and forth. Like so:

最后,您可以创建一个服务。现在,服务通常不以这种方式使用,但是您可以用这种方式使用服务。你可以带着你的篮球细节服务,用它来来回传递价值。像这样:

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>

This works because the $scope in both controllers is keeping a reference to the same object, which is maintained by your basketDetail service. But again, this isn't really the recommended way.

这之所以有效,是因为这两个控制器中的$scope都保存了对同一对象的引用,而该对象是由篮球细节服务维护的。但是,这并不是推荐的方法。

All of that said: $rootScope, IMO is most likely what you're looking for.

所有这些都说:$rootScope, IMO很可能是你想要的。

  • It doesn't require the creation of an additional controller.
  • 它不需要创建额外的控制器。
  • It doesn't require the creation of any additional function references.
  • 它不需要创建任何其他函数引用。
  • Will not cause the creation of any additional parent/child Scope nesting and subsequent watches.
  • 不会导致创建任何其他父/子范围嵌套和后续监视。

#3


2  

No real need for $rootScope. Create a parent controller (e.g. RootController) with a function on its scope. The child scopes will automatically inherit it:

根本不需要$rootScope。创建具有作用域上的函数的父控制器(例如RootController)。子作用域将自动继承它:

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


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

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

In your detail controller you just use the setBasketCount() function:

在细节控制器中,只需使用setBasketCount()函数:

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

    //more code
}