在ui-router解析中使用$ scope

时间:2022-01-22 11:14:44

I am using ui-router resolve in order to get some data from a service.

我正在使用ui-router解析来从服务中获取一些数据。

The thing is that I need to get a value from the parent $scope in order to call the service as shown bellow.

问题是我需要从父$ scope获取一个值,以便调用服务,如下所示。

resolve: {
              contactService: 'contactService',
              contacts: function ($scope, contactService) {
                  return contactService.getContacts($scope.parentCtrl.parentObjectId);
              }
          }

I keep getting Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

我一直收到错误:[$ rootScope:infdig] 10 $ digest()迭代达成。中止!

Also tried a few desperate attempts such as adding scope to the resolve object as shown bellow with not success.

还尝试了一些绝望的尝试,例如向解析对象添加范围,如下所示,但没有成功。

scope: $scope

Any ideas?

有任何想法吗?

2 个解决方案

#1


19  

That's impossible, scope hasn't been initialized at that point so you can't use it in the resolve object. You can access the scope in the controller after it's been initialized. The whole point of resolve is that it runs before controller initialization so that you can inject and directly access the resolved items in your scope.

这是不可能的,范围尚未在此时初始化,因此您无法在解析对象中使用它。初始化后,您可以访问控制器中的范围。解决问题的关键在于它在控制器初始化之前运行,以便您可以注入并直接访问范围中已解析的项目。

If you need to pass a variable to the next state you can do that by using the $stateParams object which is available for use in resolve. You can add data to it when changing states, eg:

如果需要将变量传递给下一个状态,可以使用可用于解析的$ stateParams对象来完成。您可以在更改状态时向其添加数据,例如:

In your template, if you have a objectId in your scope:

在您的模板中,如果您的范围中有objectId:

<a ui-sref="statename({'id': objectId})">Change states</a>

Or in your controller:

或者在您的控制器中:

$scope.go('statename', {'id': $scope.objectId});

You can then retrieve that in your resolve by using the $stateParams:

然后,您可以使用$ stateParams在您的解析中检索它:

resolve: {
    contactService: 'contactService',
    contacts: function ($stateParams, contactService) {
        return contactService.getContacts($stateParams.id);
    }
}

#2


0  

As an alternative to the accepted solution, which requires another round trip to the server for the same resource (if you are getting the value from the server/api) you could $watch the parent from the child controller.

作为已接受的解决方案的替代方案,它需要为服务器再次往返同一资源(如果从服务器/ api获取值),您可以从子控制器中查看父级。

function ParentController($http) {
  var vm = this;
  $http.get(someResourceUrl).then(function(res) {
    vm.someResource = res.data;
  });
}

function ChildController($scope) {
  // wait untill the parent gets the value
  var unwatch = $scope.$watch('parent.someResource', function(newValue) {
    if (newValue) {
      // the parent has the value, init this controller
      init(newValue);
      // dispose of the watcher we no longer need
      unwatch();
    }
  });
  function init(someResource) {
    // ... do something
  }
}

function routerConfig($stateProvider) {
  $stateProvider
    .state('parent', {
      url: '/parent',
      controller: 'ParentController',
      controllerAs: 'parent',
      templateUrl: '...',
    })
    .state('parent.child', {
      url: '/child',
      controller: 'ChildController',
      controllerAs: 'child',
      templateUrl: '...',
    });
}

#1


19  

That's impossible, scope hasn't been initialized at that point so you can't use it in the resolve object. You can access the scope in the controller after it's been initialized. The whole point of resolve is that it runs before controller initialization so that you can inject and directly access the resolved items in your scope.

这是不可能的,范围尚未在此时初始化,因此您无法在解析对象中使用它。初始化后,您可以访问控制器中的范围。解决问题的关键在于它在控制器初始化之前运行,以便您可以注入并直接访问范围中已解析的项目。

If you need to pass a variable to the next state you can do that by using the $stateParams object which is available for use in resolve. You can add data to it when changing states, eg:

如果需要将变量传递给下一个状态,可以使用可用于解析的$ stateParams对象来完成。您可以在更改状态时向其添加数据,例如:

In your template, if you have a objectId in your scope:

在您的模板中,如果您的范围中有objectId:

<a ui-sref="statename({'id': objectId})">Change states</a>

Or in your controller:

或者在您的控制器中:

$scope.go('statename', {'id': $scope.objectId});

You can then retrieve that in your resolve by using the $stateParams:

然后,您可以使用$ stateParams在您的解析中检索它:

resolve: {
    contactService: 'contactService',
    contacts: function ($stateParams, contactService) {
        return contactService.getContacts($stateParams.id);
    }
}

#2


0  

As an alternative to the accepted solution, which requires another round trip to the server for the same resource (if you are getting the value from the server/api) you could $watch the parent from the child controller.

作为已接受的解决方案的替代方案,它需要为服务器再次往返同一资源(如果从服务器/ api获取值),您可以从子控制器中查看父级。

function ParentController($http) {
  var vm = this;
  $http.get(someResourceUrl).then(function(res) {
    vm.someResource = res.data;
  });
}

function ChildController($scope) {
  // wait untill the parent gets the value
  var unwatch = $scope.$watch('parent.someResource', function(newValue) {
    if (newValue) {
      // the parent has the value, init this controller
      init(newValue);
      // dispose of the watcher we no longer need
      unwatch();
    }
  });
  function init(someResource) {
    // ... do something
  }
}

function routerConfig($stateProvider) {
  $stateProvider
    .state('parent', {
      url: '/parent',
      controller: 'ParentController',
      controllerAs: 'parent',
      templateUrl: '...',
    })
    .state('parent.child', {
      url: '/child',
      controller: 'ChildController',
      controllerAs: 'child',
      templateUrl: '...',
    });
}