AngularJS:使用嵌套的ng-repeat和动态创建的输入构建表单

时间:2015-12-18 07:33:14

标签: angularjs angularjs-scope angularjs-ng-repeat

我正在构建一个应该支持为同一产品的多个实例输入属性的表单。允许用户使用ng-repeat创建任意数量的实例,并在添加版本"时创建表单的其他版本。单击按钮。对于静态输入,这可以按预期工作,因为创建了新表单,并且输入的值不在实例之间链接。但是,我还打算使用ng-repeat支持单个属性的动态列表,在我当前的实现中,addVersion()函数正在复制属性的数量和其中的值。

我已就此主题阅读了several questions,我很清楚我应该使用$index,但我害怕我&#39}对Angular来说,我已经足够新了,我无法完全理解如何做到这一点。

编辑:Here's a working example that should highlight the problem

为了清楚起见,我希望能够生成如下响应:

  

产品名称:汽车
  产品描述:你可以坐在里面也开它   版本1
  价格:500美元   数量:3
  特点:1)快速2)红色
  第2版
  价格:600美元   数量:4
  特点:1)真的很快2)是蓝色3)有挡风玻璃刮水器

但相反,我看到克隆的功能中的值...这是有道理的,因为我清楚地将它们推到同一个阵列我只是不知道如何改变它:)< / p>

现在,代码的简化版本如下所示:

HTML

<form>
    <input type="text" ng-model="name" placeholder="Product Name">
    <textarea ng-model="description" placeholder="Product Description"></textarea>
    <button ng-click="addVersion()">Add Version</button>
    <!-- Additional feature inputs should be exclusive to each instance and not replicated across all -->
    <div ng-repeat="version in versions">
        <input type="number" ng-model="instance.price" placeholder="Price">
        <input type="number" ng-model="instance.quantity" placeholder="Quantity"> 
        <button ng-click="addInput()">Add Feature</button>
        <fieldset ng-repeat="feature in features">
            <input type="text" ng-model="instance.feature.name" placeholder="feature">
        </fieldset>
    </div>
</form>

JS

$scope.versions = [{}];

$scope.addVersion = function() {
    $scope.versions.push({});
};


$scope.features = [];

$scope.addInput = function() {
    $scope.features.push({});
};

我认为这里的解决方案显而易见,我只是有点迷失。谢谢!

3 个答案:

答案 0 :(得分:0)

我认为您将能够解决问题,如下所示。关键的变化是,您应该将version对象传递给addInput方法并向该实例添加功能。

我强烈建议为此任务创建一个指令。

angular.module('Form', []).controller('multipleVersions', function($scope) {

  $scope.versions = [{
    features: [{
      features: [{}]
    }]
  }];

  $scope.addVersion = function() {
    $scope.versions.push({
      features: [{}]
    });
  };

  $scope.addInput = function(version) {
    version.features.push({});
  };

  $scope.removeInput = function(version, index) {
    version.features.splice(index, 1);
  };
});
input {
  display: block;
}
#addVersionButton {
  display: block;
}
.version {
  margin-top: 20px;
  border: 1px solid black;
}
.feature {
  display: inline;
}
.removeInput {
  display: inline;
}
fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<form ng-app="Form" ng-controller="multipleVersions">
  <input type="text" ng-model="product.name" placeholder="Product Name">
  <textarea ng-model="product.description" placeholder="Product Description"></textarea>
  <button id="addVersionButton" ng-click="addVersion()">Add Version</button>
  <div class="version" ng-repeat="version in versions">
    <input type="number" ng-model="version.price" placeholder="Price">
    <input type="number" ng-model="version.quantity" placeholder="Quantity">
    <button ng-click="addInput(version)">Add Feature</button>
    <fieldset ng-repeat="feature in version.features">
      <input class="feature" type="text" ng-model="feature.name" placeholder="feature">
      <button class="removeInput" ng-click="removeInput(version,$index)">-</button>
    </fieldset>
  </div>
</form>

答案 1 :(得分:0)

我认为你只是高估变量实例...

当您使用ng-repeat时,建议您使用转发器变量...

你能试试吗?

<form>
    <input type="text" ng-model="name" placeholder="Product Name">
    <textarea ng-model="description" placeholder="Product Description"></textarea>
    <button ng-click="addVersion()">Add Version</button>
    <!-- Additional feature inputs should be exclusive to each instance and not replicated across all -->
    <div ng-repeat="version in versions">
        <input type="number" ng-model="version.instance.price" placeholder="Price">
        <input type="number" ng-model="version.instance.quantity" placeholder="Quantity"> 
        <button ng-click="addInput()">Add Feature</button>
        <fieldset ng-repeat="feature in features">
            <input type="text" ng-model="version.instance.feature.name" placeholder="feature">
        </fieldset>
    </div>
</form>

重复功能,我猜错了。我建议你之前向它添加feature.instance的功能。

提示:如果您使用Chrome浏览器进行测试,请按f12并查看“控制台”。登录。如果你访问null变量的某个属性(我的猜测),你将得到一个NullException错误。

答案 2 :(得分:-1)

感谢所有帮助过的人。所提出的解决方案都没有涵盖所有内容,但它们肯定会让我得到答案。下面分列的问题和解决方案以及原始http://plnkr.co/edit/T74bfNXxpYs16ENNUEjv?p=preview的工作版本:

动态添加输入的复制:这是通过将version传递给addInput()方法并修改js来正确处理数组来处理的:

  $scope.versions = [{
    features: [{
      features: [{}]
    }]
  }];

  $scope.addVersion = function() {
    $scope.versions.push({
      features: [{}]
    });
  };

  $scope.addInput = function(version) {
    version.features.push({});
  };

感谢T J解决方案,其中一个答案如下。这允许创建单个输入,但是文本被克隆到所有输入,并且删除按钮不再起作用。

克隆文本:每组输入都在version.feature.name写入同一模型。按照解决方案here并按$ index跟踪解决了这个问题。

删除按钮:removeInput()方法不再引用与其配对的特定输入,并要求我传入$parent.$index(以引用版本)和$index (参考具体的输入。)

下面的最终代码:

HTML:

    <form>
      <input type="text" ng-model="name" placeholder="Product Name">
      <textarea ng-model="description" placeholder="Product Description"></textarea>
      <button id="addVersionButton" ng-click="addVersion()">Add Version</button>
    <div class="version" ng-repeat="version in versions">
      <span>Instance {{$index}}</span>
        <input type="number" ng-model="version.price" placeholder="Price">
        <input type="number" ng-model="version.quantity" placeholder="Quantity"> 
        <button ng-click="addInput(version)">Add Feature</button>
        <fieldset ng-repeat="feature in version.features">
            <!-- Additional feature inputs should be exclusive to each instance and not replicated across all -->
            <input class="feature" type="text" ng-model="version.features[$index].value" placeholder="feature">
            <button class="removeInput" ng-click="removeInput($parent.$index, $index)">-</button>
        </fieldset>
    </div>
</form>

JS

  $scope.versions = [{}];

  $scope.addVersion = function() {
      $scope.versions.push({});
  };


  $scope.features = [];

  $scope.addInput = function() {
      $scope.features.push({});
  };

    $scope.removeInput = function(index) {   
    $scope.features.splice(index, 1);
  };