Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access the data from the resolve function without relading the controller

How do we access the data from the resolve function without relading the controller?

We are currently working on a project which uses angular-ui-router. We have two seperated views: on the left a list of parent elements, on the right that elements child data.

If selecting a parent on the left, we resolve it's child data to the child-view on the right.

With the goal not to reaload the childs controller (and view), when selecting a different parent element, we set notify:false.

We managed to 're-resolve' the child controllers data while not reloading the controller and view, but the data (scope) won't refresh.

We did a small plunker to demonstrate our problem here

First click on a number to instantiate the controllers childCtrl. Every following click should change the child scopes data - which does not work. You might notice the alert output already has the refreshed data we want to display.

like image 609
nilsK Avatar asked Jul 14 '16 15:07

nilsK


1 Answers

Based on sielakos answer using an special service i came up with this solution. First, i need a additional service which keeps a reference of the data from the resovle.

Service

.service('dataLink', function () {
  var storage = null;

  function setData(data) {
      storage = data;
  }

  function getData() {
      return storage;
  }

  return {
      setData: setData,
      getData: getData
  };
})

Well, i have to use the service in my resolve function like so

Resolve function

resolve: {
    detailResolver: function($http, $stateParams, dataLink) {
        return $http.get('file' + $stateParams.id + '.json')
            .then(function(response) {
                alert('response ' + response.data.id);
                dataLink.setData(response.data);
                return response.data;
            });
    }
}

Notice the line dataLink.setData(response.data);. It keeps the data from the resolve in the service so I can access it from within the controller.

Controller

I modified the controller a little. I wrapped all the initialisation suff in an function i can execute when the data changes. The second thing is to watch the return value of the dataLink.getData();

As of https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch $scope.$watch provides functionality to watch return values of functions.

Here is some Q&D example:

.controller('childCtrl', function($scope, $log, detailResolver, $interval, dataLink) {
    initialise();
    /*
    * some stuff happens here
    */

    $interval(function() {
        console.log(detailResolver.id)
    }, 1000);

    $scope.$watch(dataLink.getData, function(newData) {
        detailResolver = newData;
        initialise();
    });

    function initialise() {
        $log.info('childCtrl detailResolver.id == ' + detailResolver);
        $scope.id = detailResolver;
    }
})

The line $scope.$watch(dataLink.getData, function(newData) { ... }); does the trick. Every time the data in the dataLink service changes the callback kicks in and replaces the old data with the new one. Ive created a plunker so you can give it a try https://plnkr.co/edit/xyZKQgENrwd4uEwS9QIM

You don't have to be afraid of memory leaks using this solution cause angular is removing watchers automatically. See https://stackoverflow.com/a/25114028/6460149 for more information.

like image 94
DaVarga Avatar answered Sep 17 '22 11:09

DaVarga