简体   繁体   English

Angularjs中的动态表单名称属性<input type =“text”name =“{{variable-name}}”/>

[英]Dynamic form name attribute <input type=“text” name=“{{ variable-name }}” /> in Angularjs

How would someone use formName.inputName.$valid when the "inputName" was dynamically created? 当动态创建“inputName”时,有人会如何使用formName.inputName。$有效?

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

The output of the HTML input attribute 'name' would be the string "variablename", which would applied to ALL repeated inputs. HTML输入属性“name”的输出将是字符串“variablename”,它将应用于所有重复输入。

If we tried this 如果我们试过这个

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

The output of the HTML input attribute 'name' would be the string"{{ variable.name }}", which would be applied to ALL repeated inputs. HTML输入属性“name”的输出将是字符串“{{variable.name}}”,它将应用于所有重复输入。

In either of these two conditions, a name attribute for each of the repeated input elements would not be created dynamically; 在这两个条件中的任何一个中,都不会动态创建每个重复输入元素的name属性; ALL inputs would share the same input name. 所有输入将共享相同的输入名称。 Not much good if you wanted to call a specific input based on a specific name. 如果您想根据特定名称调用特定输入,那就太好了。

  • need to use dynamic name values 需要使用动态名称值
  • need to be able to call $scope.formName.dynamicName.$valid 需要能够调用$ scope.formName.dynamicName。$ valid
  • need to be able to call $scope.formName.$valid 需要能够调用$ scope.formName。$ valid
  • need dynamic name input fields to be added to nested form, or master form 需要动态名称输入字段添加到嵌套表单或主表单

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

This is now possible with Angular 1.3+: 现在,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 演示

In some cases an inner form is a good solution if you can just pass the information: ( https://stackoverflow.com/posts/12044600/ ) To solve the 'dynamic name' problem you need to create an inner form (see ng-form ) : 在某些情况下,如果您只是传递信息,内部表格是一个很好的解决方案:( 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>

The other alternative would be to write a custom directive for this. 另一种选择是为此编写自定义指令。

Here is the jsFiddle showing the usage of the ngForm: http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/ 这是jsFiddle显示ngForm的用法: http//jsfiddle.net/pkozlowski_opensource/XK2ZT/2/

I could not find the answer that satisfied some or all of these needs. 我找不到满足部分或全部这些需求的答案。 This is what I came up with. 这就是我提出的。

There may be a better way, so please share your thoughts. 可能有更好的方法,所以请分享您的想法。
I am using Angularjs 1.3.0-beta.8 我正在使用Angularjs 1.3.0-beta.8

I have a form with multi-nested directives that all contain input(s), select(s), etc... These elements are all enclosed in ng-repeats, and dynamic string values. 我有一个包含多嵌套指令的表单,它们都包含输入,选择等等......这些元素都包含在ng-repeats和动态字符串值中。

This is how to use the directive: 这是如何使用该指令:

<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>

Note: you can add and index to the string concatenation if you need to serialize perhaps a table of inputs; 注意:如果需要序列化输入表,则可以添加字符串并置索引; which is what I did. 这就是我做的。 However, dynamic name inputs means you may not know the name of the form input, so how would you call $scope.formName.??????. 但是,动态名称输入意味着您可能不知道表单输入的名称,因此您将如何调用$ scope.formName。??????。 You could iterate of the $scope.formName object to get keys that match a certain value. 您可以迭代$ scope.formName对象以获取与特定值匹配的键。 That means string concatenation like this: 这意味着像这样的字符串连接:

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

Then in $scope.myFormName you would find any form input name by just iterating over the object and gathering any keys that included 'hello'. 然后在$ 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
  }
});

This should handle many situations where you just don't know where the form will be. 这应该处理许多你不知道表单在哪里的情况。 Or perhaps you have nested forms, but for some reason you want to attach this input name to two forms up? 或者您可能有嵌套表单,但出于某种原因,您希望将此输入名称附加到两个表单中? Well, just pass in the form name you want to attach the input name to. 好吧,只需传入要附加输入名称的表单名称即可。

What I wanted, was a way to assign dynamic values to inputs that I will never know, and then just call $scope.myFormName.$valid. 我想要的是一种将动态值分配给我永远不会知道的输入的方法,然后只需调用$ scope.myFormName。$ valid。

This may be an overkill, and a better solution exists in 1.3+. 这可能是一种矫枉过正,1.3+中存在更好的解决方案。 I couldn't find it in the time I had. 我没有找到它。 This works for me now. 这对我来说很有用。

Good luck! 祝好运! Hope this helps someone!!!! 希望这有助于某人!!!!

work for me with angular 1.2.7 我的角度为1.2.7

directive: 指示:

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);

howtouse: 如何使用:

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

Don't forget that you can access javascript objects using array notation with string indexes. 不要忘记您可以使用带有字符串索引的数组表示法来访问javascript对象。 Given the following arbitrary form definition object : 给定以下任意形式定义对象:

$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 = {};

... and the html snippet ... ...和html片段......

<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>

Inside the controller you then would have a nice form_values object for every field which you can access by iterating over the keys in the form_def.variables hash. 在控制器内部,您可以为每个字段提供一个很好的form_values对象,您可以通过迭代form_def.variables散列中的键来访问它们。

There is a lot more involved once you get down into writing these sort of generic form processing scripts and you end up with a hell of a lot of spaghetti code in my opinion and you would probably be better of going with a less general solution, but thats another SO question. 一旦你开始编写这些通用的表单处理脚本,你就会涉及到更多的内容,在我看来,你最终会得到很多意大利面条代码,你可能会更好地使用不那么通用的解决方案,但是这是另一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM