Подтвердить что ты не робот

Обновление HTML-элемента вне ng-view

У меня есть следующий 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. Оба способа ничего не делают.

Может кто-нибудь помочь?

Спасибо

4b9b3361

Ответ 1

Ваш 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>

Ответ 2

Вам нужно будет ввести $rootScope, а затем обновить его:

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

    //more code
}

Есть много способов сделать это, но это мое первое предложение, потому что оно, вероятно, самое легкое.


EDIT: по вашему запросу, другие способы сделать это...

Вы можете использовать $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, ИМО, скорее всего, то, что вы ищете.

  • Это не требует создания дополнительного контроллера.
  • Это не требует создания каких-либо дополнительных ссылок на функции.
  • Не приведет к созданию каких-либо дополнительных родительских/дочерних объектов. Вложенность и последующие часы.

Ответ 3

Нет необходимости в $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
}