angular.js icon indicating copy to clipboard operation
angular.js copied to clipboard

Way to retrieve ng-minlength/maxlength value in form object

Open jonricaurte opened this issue 10 years ago • 13 comments

I was looking through the form object and it doesn't seem I can see the actual value that is being set for ng-minlength="6". Is it possible to get the 6 from the form object?

Thanks.

jonricaurte avatar Apr 21 '15 20:04 jonricaurte

Yes. You can get it via its attributes

wonderfan avatar Apr 22 '15 09:04 wonderfan

@jonricaurte Send an example of what you really want to do

bruunofco avatar Apr 22 '15 20:04 bruunofco

Here's a solution I think you'll be happy with... Here's a working jsbin

HTML:

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
    <meta charset="utf-8">
    <title>JS Bin</title>
  </head>
  <body ng-app="app" ng-controller="MainCtrl as vm">
    <div>
      <form name="vm.myForm">
        <input name="myInput" id="theInput" ng-model="foo" ng-minlength="2" ng-maxlength="{{vm.max}}" />
      </form>
    </div>
    <hr />
    <div>
      Can't get it from the NgModelController normally:
      <pre>{{vm.normalNgModelCtrl | json}}</pre>
    </div>
    <hr />
    <div>
      But you could write your own <code>ng-model</code> directive which will be used in addition to
      the normal directive and publish those values to the controller
      <pre>{{vm.myForm.myInput | json}}</pre>
    </div>
    <hr />
    <div>
      It can even be dynamic :-)
      <input type="number" ng-model="vm.max" />
    </div>
    <hr />
    <div>
      Or you could always hack it with some regular JavaScript... &lt;shudders-in-fear&gt;
      <div>
        Minlength: <span id="minlength"></span>
      </div>
      <div>
        Maxlength: <span id="maxlength"></span>
      </div>
    </div>
  </body>
</html>

JavaScript

var app = angular.module('app', []);

app.controller('MainCtrl', function() {
  var vm = this;

  vm.max = 6;

  vm.normalNgModelCtrl = {
    "$validators": {},
    "$asyncValidators": {},
    "$parsers": [],
    "$formatters": [
      null
    ],
    "$viewChangeListeners": [],
    "$untouched": true,
    "$touched": false,
    "$pristine": true,
    "$dirty": false,
    "$valid": true,
    "$invalid": false,
    "$error": {},
    "$name": "myInput",
    "$options": null
  };
});

app.directive('ngModel', function attributeNgModelDirective() {
  return {
    require: 'ngModel',
    link: function(scope, el, attrs, ctrl) {
      ctrl.attributes = attrs;
    }
  };
});

// regular JavaScript... probably don't need to do it this way...
(function() {
  var inputEl = document.getElementById('theInput');
  var minlengthEl = document.getElementById('minlength');
  var maxlengthEl = document.getElementById('maxlength');
  minlengthEl.innerText = inputEl.getAttribute('ng-minlength');
  maxlengthEl.innerText = inputEl.getAttribute('ng-maxlength');
})();

kentcdodds avatar Apr 23 '15 16:04 kentcdodds

@kentcdodds: Your sample codes make sense.

wonderfan avatar Apr 24 '15 02:04 wonderfan

I was thinking more of something like this:

http://plnkr.co/edit/w4Rr38yqxgb1nh3GocEZ?p=preview

jonricaurte avatar Apr 24 '15 19:04 jonricaurte

You could use the directive I showed you above to accomplish this.

As a side note, if you're looking for advanced forms using angular... Look no further than angular-formly. Here's an example that does something similar to what I think what you're trying to accomplish... http://angular-formly.com/#/example/other/error-summary

kentcdodds avatar Apr 24 '15 20:04 kentcdodds

I feel like this is a valid feature request. The error object should include something that specifies the value of ng-minlength/maxlength and the others.

jonricaurte avatar Apr 24 '15 20:04 jonricaurte

I see now what you are asking. You want the $error object to have meta-data about the validator used to cause an error. If that's correct, then that's a different conversation than I thought we were having :-) Until something like that gets enough interest, I don't see the angular team adding this feature to angular core. However, with the workaround I suggested, I think it'll work just fine for what you're looking for. Also, if you're doing a lot of forms in your app, I highly recommend using angular-formly which simplifies the forms API considerably.

kentcdodds avatar Apr 24 '15 20:04 kentcdodds

It's all good :) I feel like this is a common use case especially seeing something like angular valdr and angular-formly and how they have to have text for every kind of error instead of reusing the same template for everything. Here is another example use case for more than one on same element:

http://plnkr.co/edit/VGDFuJfscZVBpvTGCgUu?p=preview

Also if you wanted to do something with translations you could add a filter (very basic example):

http://plnkr.co/edit/bVh6rc1L9edFfErIumFI?p=preview

jonricaurte avatar Apr 24 '15 21:04 jonricaurte

they have to have text for every kind of error instead of reusing the same template for everything

Not sure what you mean by this. You can pretty easily make a template with angular-formly to show a dynamic the error message based on the error. Would appreciate an issue on angular-formly if you think the API could be improved :-)

kentcdodds avatar Apr 24 '15 21:04 kentcdodds

I should have clarified. Will leave a comment in the issues if I am misunderstanding something and will leave this ticket open as a feature request to hopefully be able to use forms like this later.

jonricaurte avatar Apr 24 '15 21:04 jonricaurte

Very useful feature to have. Meta data is sometimes needed through custom validation process.

DigitalSmile avatar Sep 04 '15 12:09 DigitalSmile

I need this metadata for simplifying an all-in validator component.

Something like:

<label for="Password">Password</label>
<input class="form-control" type="password" ng-model="me.Password" id="Password" name="Password" minlength="8" maxlength="72" required="required" />
<validation-message input="UserCreateForm.Password" param-maxlength="72" param-minlength="8"></validation-message>

I wish can simplify the component and do this instead:

<label for="Password">Password</label>
<input class="form-control" type="password" ng-model="me.Password" id="Password" name="Password" minlength="8" maxlength="72" required="required" />
<validation-message input="UserCreateForm.Password"></validation-message>

ryanelian avatar Sep 11 '16 12:09 ryanelian