使用ui-router更改状态时如何保留范围数据?

时间:2019-02-03 22:36:27

标签: angularjs angular-ui-router

我正在使用AngularJS和ui-router构建一个单页Web应用程序。我有两个不同的州,一个父母和一个孩子。在父状态“ spots”中,用户可以从ng-repeat中进行选择,并使用范围显示其选择。

当用户进行选择时,我用ng键单击fire一个使用$ state.go加载子状态“明细”的函数。我想在子状态下加载它们的选择,但范围数据似乎消失了?

我尝试为每个状态使用相同的控制器。 ui-sref也不起作用。

来自父州HTML模板

<div class="card-column mx-0" data-ng-click="makeSelection = true">

 <div class="card mx-0 mb-3 ng-scope" data-ng-click="showSpot(spot);" data-ng-repeat="spot in spots | filter:{'game':gameID} | filter:{'walking':distanceID} | filter:{'vehicle':vehicleID} | orderBy:'price' | filter as results">
   <div class="row no-gutters">

    <div class="col-sm-12 col-md-3 col-lg-3">
      <img src="{{ spot.image }}" alt="parking spot"/>
    </div>

    <div class="col-sm-12 col-md-9 col-lg-9">
      <div class="card-body px-4 pt-4">

        <h6 class="text-small-extra text-muted font-weight-normal text-uppercase"><span style="letter-spacing: .05rem;">{{ spot.type }}</span></h6>

        <h5 class="card-title">{{ spot.address }}</h5>

        <h4 class="text-muted float-md-right">${{ spot.price }}<span style="font-size: 1rem; font-weight: 400">/day</span></h4>

      </div>

    </div>

  </div>

</div>

控制器的摘录

$scope.showDetails = function() {
  $state.go('spots.details'); //my route...
}

$scope.showSpot = function(spot) {
  $scope.spot = spot;
  $scope.showDetails();
}

来自app.js的代码段

.config(function($stateProvider, $urlRouterProvider) {

$urlRouterProvider.otherwise("/")

$stateProvider
.state('spots',{
  url: '/',
  templateUrl: "/parkit/master/spots-available.html",
  controller: 'parkitController'
})
.state('details', {
  parent: 'spots',
  url: '/details',
  templateUrl: '/parkit/master/details.html',
})
.state('statetwo', {
  url: '/statetwo',
  template: '<h1>State Two</h1>',
  controller: 'parkitController'
});

})

我希望用户选择会在触发ng-click之后显示在子状态上。

1 个答案:

答案 0 :(得分:1)

您需要了解原型继承的工作方式。当父母使用

将属性值放在作用域上时
$scope.value = 'something';

在子组件中,如果您访问$ scope.value,则继承链将找到$ scope.value。

如果孩子设置了

$scope.otherValue = 'something';

如果遵循继承链,则不会找到otherValue的值并在子作用域上创建属性,而不是在继承的原型上创建属性,因此父组件和父级的任何其他子项都看不到它。

您可以使用所谓的原型继承的点规则。如果父级在作用域上创建了一个称为数据的对象

$scope.data = { value: 'something' };

现在,如果孩子将属性放在数据对象上

$scope.data.otherValue = 'something';

它会查找数据对象,并在继承链中找到它,并且因为您正在向对象的实例添加属性,因此它对父级和父级的任何子级都是可见的。

let parent = {
  value: 'some value',
  data: { value: 'some value' }
};

let child = Object.create(parent);

console.log(child.value); // Finds value on the prototype chain

child.newValue = 'new value'; // Does not affect the parent

console.log(parent.newValue);

child.data.newValue = 'new value'; // newValue is visible to the parent

console.log(parent.data.newValue);

简短的答案是永远不要注入$ scope并使用controllerAs语法。

要在控制器之间共享数据,请使用注入到两个控制器中的服务。您在服务上具有了Spots集合,并使用路由参数来确定另一个控制器应使用哪个地点,或在另一个控制器上设置的名为currentSpot的服务上具有位置。

服务是您在模块级别创建的单例对象,然后在其依赖项列表中要求它们的所有控制器都将获得相同的实例。它们是在控制器之间共享数据的首选方式,$ scope层次结构势必会引起混乱,因为它们的原型继承性质可能会造成混淆。子级$ scope原型是从其父级继承的,这似乎应该共享数据,但是当子级控制器设置属性时,父级不可见。

您正在学习一种过时的Angular编程方式。不再推荐使用$ scope注入。查看使用组件。组件是具有隔离范围并使用contollerAs语法的控制器的包装。孤立的作用域使人们更清楚地知道数据的来源。

看看我对这个问题的回答

Trying to activate a checkbox from a controller that lives in another controller