【问题标题】:Dynamic form name attribute <input type="text" name="{{ variable-name }}" /> in AngularjsAngularjs中的动态表单名称属性<input type="text" name="{{ variable-name }}" />
【发布时间】:2015-01-20 04:36:54
【问题描述】:

当动态创建“inputName”时,有人会如何使用 formName.inputName.$valid?

  <form name="formName">
    <input ng-repeat="(variable) in variables"
           type="text" name="variable.name"
           ng-model="variable.name" required />
 </form>

HTML 输入属性“名称”的输出将是字符串“变量名称”,它将应用于所有重复的输入。

如果我们尝试这样做

<form name="formName">
  <input ng-repeat="(variable) in variables"
         type="text" name="{{ variable.name }}"
         ng-model="variable.name" required />
</form>

HTML 输入属性 'name' 的输出将是字符串“{{ variable.name }}”,它将应用于所有重复的输入。

在这两种情况下,每个重复输入元素的名称属性都不会动态创建;所有输入将共享相同的输入名称。如果您想根据特定名称调用特定输入,那就不好说了。

  • 需要使用动态名称值
  • 需要能够调用$scope.formName.dynamicName.$valid
  • 需要能够调用$scope.formName.$valid
  • 需要将动态名称输入字段添加到嵌套表单或主表单中

【问题讨论】:

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


【解决方案1】:

看起来 Angular 1.3 修复了这个问题 (https://stackoverflow.com/a/32907176/3854385)

现在可以使用 Angular 1.3+:

<form name="vm.myForm" novalidate>
  <div ng-repeat="p in vm.persons">
    <input type="text" name="person_{{$index}}" ng-model="p" required>
    <span ng-show="vm.myForm['person_' + $index].$invalid">Enter a name</span>
  </div>
</form>

Demo

在某些情况下,如果您可以传递信息,则内部表单是一个很好的解决方案:(https://stackoverflow.com/posts/12044600/) 要解决“动态名称”问题您需要创建一个内部表单(请参阅ng-form

<div ng-repeat="social in formData.socials">
      <ng-form name="urlForm">
            <input type="url" name="socialUrl" ng-model="social.url">
            <span class="alert error" ng-show="urlForm.socialUrl.$error.url">URL error</span>
            <button ng-click="doSomething(urlForm.socialUrl.$valid)">Test</button>
      </ng-form>
  </div>

另一种选择是为此编写自定义指令。

这里是显示 ngForm 用法的 jsFiddle:http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/

【讨论】:

  • ng-show="vm.myForm['person_{{$index}}'].$invalid" 应该是 ng-show="vm.myForm['person_' + $index]。 $invalid" 它需要一个计算结果为字符串而不是字符串的表达式
  • 这意味着这两者将是等价的,对吗?或者您是否收到第一个选项的错误? (我使用的是 Angular 1.x,所以它肯定可以在那里工作。如果你在 2.x 上,他们可能已经改变了它评估事物的方式。)
  • Angular 1.x 这是一个来自 Angular 文档的 plunkr 修改为使用我建议的方法 plnkr.co/edit/meW6azMBI60ZiRA1GQcU?p=preview 这是一个使用插值方法 plnkr.co/edit/ibzhEhCNPLqZCflXHLW3?p=preview 的 plunkr,因为你可以看到它导致 ngMessages 值不是被正确解析
  • ngMessages 读取值与 ngShow 的方式似乎有所不同。 plnkr.co/edit/clYtzWGC4CJl7xgI2UJO?p=preview 我的方法适用于 ng-show,但您的方法适用于两者,因此它是一个更好的解决方案。我会更新答案。
  • 这是一个有趣的怪癖,你认为它可能与指令优先级有关吗?我一直认为 {{ 插值优先于大多数指令,除了 ng-bind 和 likes
【解决方案2】:

我找不到满足部分或全部这些需求的答案。这就是我想出的。

可能有更好的方法,所以请分享您的想法。
我正在使用 Angularjs 1.3.0-beta.8

我有一个包含多嵌套指令的表单,所有指令都包含输入、选择等... 这些元素都包含在 ng-repeats 和动态字符串值中。

这是指令的使用方法:

<form name="myFormName">
  <nested directives of many levels>
    ex: <input ng-repeat=(index, variable) in variables" type="text"
               my-name="{{ variable.name + '/' + 'myFormName' }}"
               ng-model="variable.name" required />
    ex: <select ng-model="variable.name" ng-options="label in label in {{ variable.options }}"
                my-name="{{ variable.name + '/' + 'myFormName' }}"
        </select>
</form>

注意:如果您可能需要序列化输入表,您可以添加和索引字符串连接;这就是我所做的。但是,动态名称输入意味着您可能不知道表单输入的名称,那么您将如何调用 $scope.formName.??????。您可以迭代 $scope.formName 对象以获取与某个值匹配的键。这意味着像这样的字符串连接:

my-name="{{ dynamicString + hello + '/' + 'myFormName' }}"

然后在 $scope.myFormName 中,您只需遍历对象并收集包含“hello”的任何键即可找到任何表单输入名称。

app.directive('myName', function(){

  var myNameError = "myName directive error: "

  return {
    restrict:'A', // Declares an Attributes Directive.
    require: 'ngModel', // ngModelController.

    link: function( scope, elem, attrs, ngModel ){
      if( !ngModel ){ return } // no ngModel exists for this element

      // check myName input for proper formatting ex. something/something
      checkInputFormat(attrs);

      var inputName = attrs.myName.match('^\\w+').pop(); // match upto '/'
      assignInputNameToInputModel(inputName, ngModel);

      var formName = attrs.myName.match('\\w+$').pop(); // match after '/'
      findForm(formName, ngModel, scope);
    } // end link
  } // end return

  function checkInputFormat(attrs){
    if( !/\w\/\w/.test(attrs.rsName )){
      throw myNameError + "Formatting should be \"inputName/formName\" but is " + attrs.rsName
    }
  }

  function assignInputNameToInputModel(inputName, ngModel){
    ngModel.$name = inputName
  }

  function addInputNameToForm(formName, ngModel, scope){
    scope[formName][ngModel.$name] = ngModel; return
  }

  function findForm(formName, ngModel, scope){
    if( !scope ){ // ran out of scope before finding scope[formName]
      throw myNameError + "<Form> element named " + formName + " could not be found."
    }

    if( formName in scope){ // found scope[formName]
      addInputNameToForm(formName, ngModel, scope)
      return
    }
    findForm(formName, ngModel, scope.$parent) // recursively search through $parent scopes
  }
});

这应该可以处理许多您只是不知道表单在哪里的情况。或者您可能有嵌套的表单,但出于某种原因您想将此输入名称附加到两个表单上?好吧,只需传入要附加输入名称的表单名称即可。

我想要的是一种将动态值分配给我永远不会知道的输入的方法,然后只需调用 $scope.myFormName.$valid。

这可能有点矫枉过正,更好的解决方案存在于 1.3+ 中。我当时找不到。现在这对我有用。

祝你好运!希望这对某人有帮助!!!!

【讨论】:

  • 绝对有助于解决我的嵌套情况。我做了一个小的更正:在checkInputFormat 函数中,您应该检查attrs.myName
  • 哦,顺便说一句,AngularJS 1.3+ 中存在什么更好的解决方案?
  • 我还没找到。我会继续寻找。
  • 希望对您有所帮助:stackoverflow.com/questions/21455695/…
【解决方案3】:

使用 angular 1.2.7

为我工作

指令:

var DynamicName = function() {
    return {
        restrict: 'A',
        priority: -1,
        require: ['ngModel'],
        link: function (scope, element, attr, ngModel) {
            ngModel[0].$name = attr.name;
        }
    };
};

app.directive('dynamicName', DynamicName);

如何使用:

<div ng-repeat="phone in hrModel.phones">
    <input type="text"
           name="phones[{{$index}}]"
           ng-model="phones[$index]"
           dynamic-name
    />
</div>

【讨论】:

    【解决方案4】:

    不要忘记,您可以使用带有字符串索引的数组表示法访问 javascript 对象。给定以下任意表单定义对象:

    $scope.form_def = {
      form_name : 'BallForm',
      variables : [
        height : { name : 'Height', type : 'text' },
        width : { name : 'Width', type : 'text' },
        color : { name : 'Color', type : 'multi', options : ['red', 'green', 'blue'] }
      ]
    };
    $scope.form_values = {};
    

    ... 和 html sn-p ...

    <form name="{{ form_def.form_name }}">
      <div ng-repeat="variable in form_def.variables">
        <input ng-if="variable.type==='text'" type="text" name="{{ variable.name }}" ng-model="form_values[variable.name]">
        <select ng-if="variable.type==='multi'" name="{{ variable.name }}" ng-model="form_values[variable.name]">
          <option ng-repeat="opt in variable.options" value="{{ opt }}">{{ opt }}</option>
        </select>
      </div>
    </form>
    

    在控制器内部,您将为每个字段创建一个不错的 form_values 对象,您可以通过遍历 form_def.variables 哈希中的键来访问该对象。

    一旦你开始编写这些通用的表单处理脚本,就会涉及到更多的事情,而且在我看来,你最终会得到大量的意大利面条代码,你可能会更好地使用不那么通用的代码解决方案,但那是另一个 SO 问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-31
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多