Представление не обновляется при обновлении модели в AngularJS

Я прочитал темы по этой теме, такие как: В AngularJS не обновляется вид, но я до сих пор не могу понять, как применить его на моем простом примере.

У меня есть эта функция:

function MyPageView($scope) {
  var myModel = new MyModel();
  $scope.myModel = myModel;
}

когда myModel обновляется в другом месте кода (когда пользователь щелкает, взаимодействует, отправляет запросы XHR), он не обновляет мое представление. Я понимаю, что мне нужно что-то сделать с помощью $apply, но я не понимал, где и как.

Может кто-нибудь объяснить мне, как решить эту проблему для этого простого случая использования?

Моя модель выглядит примерно так (если это необходимо для вопроса) - внутри нее нет кода AngularJS:

var MyModel = function() {
  var _this = this;
  ...
  _this.load = function(){...};
  _this.updateModel = function(){...};
  ...
  return _this;
}

добавить пример JSfiddle: http://jsfiddle.net/DAk8r/2/

Ответ 1

Суть вашей проблемы в том, что вы пытаетесь смешивать AngularJS с очень традиционным шаблоном JavaScript jQuery-soup style. В Angular вы всегда должны использовать директивы для манипуляции и взаимодействия с DOM (включая клики). В этом случае ваш код должен выглядеть следующим образом:

<div ng-controller="myModelCtrl">
  <div>Number is {{myModel.number}}</div>
  <a ng-click="myModel.updateNumber()">Update Number</a>
</div>
function myModelCtrl($scope) {
   var myModel = new MyModel();
   $scope.myModel = myModel;
}

function MyModel() {
  var _this = this;

  _this.number = 0;

  _this.updateNumber = function() {
     _this.number += 1;
    alert('new number should display ' + _this.number);
  }

  return _this;
}

Обратите внимание, что вместо настройки ручного обработчика click с jQuery мы используем Angular встроенную директиву ng-click. Это позволяет нам привязываться к жизненному циклу области Angular и правильно обновлять представление, когда пользователь нажимает на ссылку.

Вот цитата из Часто задаваемых вопросов по AngularJS; Я выделил часть, которая может помочь вам нарушить привычку.

Общие ошибки

Поддерживающий канал Angular (#angularjs on Freenode) видит ряд повторяющихся ошибок, с которыми сталкиваются новые пользователи Angular. Этот документ призван указать на них, прежде чем вы обнаружите их в трудном положении.

Манипуляция DOM

Остановите попытку использования jQuery для изменения DOM в контроллерах. В самом деле. Это включает в себя добавление элементов, удаление элементов, извлечение их содержимого, их отображение и скрытие. Используйте встроенные директивы или, если необходимо, самостоятельно создайте свои собственные манипуляции с DOM. См. Ниже о дублирующих функциях.

Если вы пытаетесь нарушить привычку, подумайте об удалении jQuery из вашего приложения. В самом деле. Angular имеет службу $http и мощные директивы, которые делают ее почти всегда ненужной. Angular В комплекте jQLite есть несколько функций, наиболее часто используемых при написании директив Angular, особенно связанных с событиями.

Наконец, вот ваш пример, работающий с использованием этого метода: http://jsfiddle.net/BinaryMuse/xFULR/1/

Ответ 2

попробуйте $scope. $apply() внутри вашего контроллера после обновления вашей модели

Ответ 3

http://jsfiddle.net/zCC2c/

Ваша проблема двоякая.

1) В вашем jsfiddle произошла синтаксическая ошибка, так как DOMElements (например, возвращаемый значением $(this) внутри вашего кликера по щелчку не предотвращает дефолт. Фактически вам нужно передать событие. (Незначительная проблема синтаксиса).

2) Поместив определение переменной в область контроллеров следующим образом:

 function MyCtrl($scope){
     $scope.foo = foo;
 }

Вы гарантируете, что он будет запущен один раз для создания экземпляра класса.

Что вы хотите:

 function MyCtrl($scope){
      $scope.someAngularClickHandler=function(){
         $scope.foo = foo;
      }
 }

И затем по вашей ссылке

   <a href="foo" id="bar" ng-click="someAngularClickHandler()">

Для более полного кода см. связанный jsfiddle.

Хороший обзор теории можно найти в первом разговоре здесь:

http://www.youtube.com/watch?feature=player_embedded&v=VxuN6WO3tIA

Ответ 4

В Angular приложениях модели обычно иногда реализуются в области $scope, а не как отдельный объект JavaScript. Ниже приведено описание вашего приложения, показывающее, как это сделать.

function myModelCtrl($scope) {
  $scope.number = 0;
  $scope.updateNumber = function () {
    $scope.number += 1;
    alert('new number should display ' + $scope.number);
  }
}

HTML:

<div ng-controller="myModelCtrl">
  <div>Number is {{number}}</div> 
  <a ng-click="updateNumber()">Update Number</a>
</div>

Здесь fiddle без jQuery, и он показывает "обычный способ" настройки скрипта для Angular.