Как мне повторно создать контроллер AngularJS после изменения данных?

Я посмотрел и предположил, что это просто, но просто не смог понять документацию API для этого.

Предположим, у меня есть контроллер, который извлекает данные при первом вызове (конечно, я опускаю тонну):

myCtrl = function ($scope, Data) {
  $scope.data = [];

  data_promise = Data.getData(); //a $http service
  data_promise.success(function (data) {
    $scope.data = data;
  });
}

Это прекрасно работает, и когда страница загружается, я получаю $scope.data заполненным именно так, как мне нужно. Однако, конечно, пользователь может пожелать обновить данные. Предположим, что простая служба "Data.save()" вызывается, когда сервер нажимает кнопку "сохранить" в форме:

myApp.factory('Data', function ($http) {
  save: function (data) {
    $http({
      method: 'POST',
      url: 'someURL',
      data: data,
    }).success(function(){
      //something here that might trigger the controller to refresh
    });
  };
});

Что бы я добавил в обратный вызов успеха, который мог бы повторно создать экземпляр контроллера, чтобы у него были самые последние данные с сервера? В настоящее время мне приходится обновлять страницу, чтобы получить обновленные данные. Сейчас я не беспокоюсь о минимизации обращений к серверу за счет кэширования результатов и изменений. Мне просто нужно сначала заставить это работать.

Спасибо!


person MyTimeFinder    schedule 27.04.2013    source источник


Ответы (2)


Вам не нужно обновлять. Просто измените обновленные данные в ControllerScope.

Это должно работать.

myApp.factory('Data', function ($http) {
  save: function (data, $scope) {
    $http({
      method: 'POST',
      url: 'someURL',
      data: data,
    }).success(function(){
      $scope.data = newData;
      //something here that might trigger the controller to refresh
    });
  };
});

// in your controller
Data.save(data, $scope);

Но: так поступать не следует. Это выглядит грязно. Используйте службы или события, которые вы отслеживаете, чтобы дождаться изменений, возвращаемых службой.

person TheHippo    schedule 27.04.2013
comment
Это грязно и на самом деле не сработает для меня. Моя вина, пример был слишком упрощен. Правда в том, что у меня есть объект $scope.allData, который (опять же упрощенно) является комбинированным результатом нескольких сервисов (представьте, что $q.all([service1, service2, service3, ...]).then(function([result1 , результат2,...]){много манипуляций});). Изменения в одном наборе данных требуют пересчета объединенного объекта. У меня даже есть несколько объектов, которые объединяют некоторые источники данных, но не все. - person MyTimeFinder; 28.04.2013
comment
Не могли бы вы объяснить, что вы подразумеваете под услугами, которые вы смотрите? Есть ли способ посмотреть Data.save(), чтобы узнать, вызывается ли он? Даже если я это сделаю, разве я не должен сказать ему что-то сделать? Как мне обновить все остальные объекты области без вызова какой-либо функции? - person MyTimeFinder; 28.04.2013
comment
Просто для ясности: на самом деле у меня есть несколько объектов области, которые необходимо обновлять, когда пользователь обновляет один источник данных. Обработка данных после извлечения до того, как они будут назначены объекту области действия, не является тривиальной и включает в себя несколько объектов-обещаний. Кажется, что в конечном итоге я бы воссоздал большую часть функции контроллера в обратном вызове Data.save().success(). Как вы сказали, это очень грязно. --Спасибо. - person MyTimeFinder; 28.04.2013
comment
Хорошо.. Это более сложно, как я предполагал. Если вам необходимо обновить модель в нескольких контроллерах. Вы пытались использовать события для оповещения всех контроллеров об изменениях? - person TheHippo; 28.04.2013

Хорошо, хотя я уверен, что есть лучший ответ, который у меня есть. По сути, я беру важные части контроллера и помещаю их в обратный вызов успеха. Чтобы не выглядеть беспорядочно, я поместил все части контроллера, которые нужно обновить, в именованную функцию.

myCtrl = function ($scope, Data, $q) {

// Binding the Data
  var updateAll;
  updateAll = function () {

    $scope.data1 = [];
    $scope.data2 = [];
    $scope.data3 = [];
    $scope.data4 = [];

    service_promise1 = Data.getData1(); //a $http service
    service_promise2 = Data.getData2();
    service_promise3 = Data.getData3();
    service_promise4 = Data.getData4();

    $q.all([service_promise1,service_promise2,service_promise3,service_promise4])
    .then(function([service1,service2,service3,service]){
      $scope.data1 = service1 + service2 //I know this isn't valid Javascript
      // just for illustration purposes
      $scope.data2 = service2 - service1 + service 3
      //etc...
    });
  };
  updateAll();


//Form Section  
$("#myForm').dialog({
  buttons: {
     Save: function () {
       Data.save(data).success(function(){
          updateAll();
        });
      }
    }
  });
}

Разбивая это, я обернул все назначения для объектов области, которые полагаются на службы, в функцию updateAll и вызываю ее при создании экземпляра myCtrl. В форме, которая обновляет данные, я вызываю функцию updateAll() после успешного выполнения функции Data.save().

Признаюсь, это не совсем операция на головном мозге, но я запутался в $scope.$apply() и подумал о простом вызове myCtrl(). Это как-то походило на "Angular", но ни то, ни другое не сработало. Я предполагаю, что функция контроллера запускается только один раз при обновлении страницы, и у Angular нет способа вызвать ее снова.

person MyTimeFinder    schedule 27.04.2013