使用对象/数组作为复选框值并跨控制器共享

时间:2014-01-02 18:16:45

标签: angularjs

我有一个由两部分组成的表单,其中一个页面允许用户通过多个列表中的复选框进行选择。完成这些选择后,用户可以在另一页上看到选择摘要。然后,用户可以返回复选框列表并根据需要选中/取消选中。

我可以让它工作,因此用户的选择仍然存在,但是我无法在主页面(摘要列表)上正确显示输出。或者,如果我使用item.name很好地显示输出,那么当用户返回到辅助页面的复选框列表时,我无法继续选择。实际上,跨控制器共享不是问题。这里的问题是当用户返回复选框列表时,使复选框保持其检查状态。例如,当我输出{{checkedCity}}时,我可以看到其中的所有内容。我只是无法获得反映这一点的复选框。

这似乎围绕着如何在工厂中输入数据:如果我在复选框输入中使用value =“item.name”,那么名称字符串就是添加到工厂的所有内容。但我也需要id,因为那就是我将实际发送api的内容。因此,如果我更改为value =“item”,那么我可以使输出看起来不错,并且我得到了id - 但是如果用户重新访问页面,我就不会得到持久性。

我的直觉(遗憾地让我无处可去)是工厂无法看到它包含的对象与复选框ng-repeat中吐出的对象相同。我已经尝试过ng-click,ng-checked,现在我正在尝试使用webStorage插件。我还尝试在工厂中循环并将其与复选框列表进行比较。

这里的插件:http://plnkr.co/edit/akvFJrPP7YtOoNBDS0Hx?p=preview

解决这个问题的最佳方法是什么?无论我如何存储信息,基本问题仍然是我似乎无法获得复选框列表以与存储的内容进行协调,以便知道检查了某些内容。

许多人提前感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

真正的解决方案是制作一个支持表达式的ngTrueValue指令,以便ngModel可以在选中复选框时注册对象或数组。不幸的是,它目前只支持字符串。 ngTrueValue很可能会在不久的将来更新,因此使用ngTrueValue很快就会成为正确的方法。

目前,您可以创建一个额外的对象/数组作为复选框的模型,并使用该组数据来确定要显示的内容。

基本和通用示例:

<强> Live Demo (click).

<强>标记:

<div ng-controller="myCtrl1">
  <div ng-repeat="item in shared.data track by $index">
    <input type="checkbox" ng-model="shared.checks[$index]"/>
    <span>{{item.name}}</span>
  </div>
</div>
<div ng-controller="myCtrl2">
  <h2>Checked:</h2>
  <div ng-repeat="item in shared.checks track by $index" ng-show="item===true">{{shared.data[$index].name}}</div>
</div>

<强> JavaScript的:

app.controller('myCtrl1', function($scope, myService) {
  $scope.shared = myService;
});

app.controller('myCtrl2', function($scope, myService) {
  $scope.shared = myService;
});

app.factory('myService', function() {
  var myService = {
    data: [
      {name:'Foo'},
      {name:'Bar'},
      {name:'Baz'},
      {name:'Qux'}
    ],
    checks: []
  };
  return myService;
});

您的代码改编:

<强> Live demo (click).

请注意,我已将checkboxFactory更改为checkboxService。工厂返回(创建)服务,因此将服务本身称为工厂是奇怪的。此外,我摆脱了许多不需要或似乎不相关的东西。

<强> JavaScript的:

app.controller('Ctrl', function($scope, checkboxService) {
  $scope.items = ['city', 'state'];
  $scope.selection = $scope.items[0];
  $scope.shared = checkboxService;
});

app.controller('AllCtrl', function($scope, checkboxService) {
    $scope.shared = checkboxService;
});

app.factory('checkboxService', function() {
  var checkboxService = {
    city: [
      {"id" : 1, "name" : "Firstplace"},
      {"id" : 2, "name" : "Second place"},
      {"id" : 3, "name" : "Thirdplace"},
      {"id" : 4, "name" : "Fourthplace"},
      {"id" : 5, "name" : "Fifth place"}
    ],
    state: [
      {"id" : 6, "name" : "yellow dog"},
      {"id" : 7, "name" : "bluedog"},
      {"id" : 8, "name" : "cobalt dog"},
      {"id" : 9, "name" : "purple dog"},
      {"id" : 10, "name" : "greendog"}  
    ],
    checks: {
      city: [],
      state: []
    }
  };
  return checkboxService;
});

<强>标记:

  <div ng-controller="Ctrl">
FIRST PAGE: make choices<br/>
  <select ng-model="selection" ng-options="item for item in items">
  </select>
  <hr/>
  <div ng-switch="" on="selection">
      <div ng-switch-when="city">
        <input ng-model="searchText">
        <div ng-repeat="item in shared.city | filter:searchText track by $index">
          <div class="checkbox-box">
            <label>
              <input type="checkbox" ng-model="shared.checks.city[$index]"/>
              <span class="labelText">{{item.name}} {{item.id}}</span>
            </label>
          </div>
        </div>
      </div>
      <div ng-switch-when="state">
        <input ng-model="searchText">
        <div ng-repeat="item in shared.state | filter:searchText track by $index">
          <div class="checkbox-box">
            <label>
              <input type="checkbox" ng-model="shared.checks.state[$index]"/>
              <span class="labelText">{{item.name}}</span>
            </label>
          </div>
        </div>
      </div>
      <div ng-switch-default></div>
  </div>
</div>

<div ng-controller="AllCtrl">
   <hr/>  
   SECOND PAGE: show choices made<br/>
        <div ng-repeat="item in shared.checks.city track by $index" ng-show="item===true">
          <div class="selected-box1">{{shared.city[$index].name}} {{item.id}}<i class="fa fa-times-circle fa-lg pull-right"></i></div>
        </div>  
        <div ng-repeat="item in shared.checks.state track by $index" ng-show="item===true">
          <div class="selected-box2">{{shared.state[$index].name}}<i class="fa fa-times-circle fa-lg pull-right"></i></div>
        </div>
</div>