Skip to content
This repository was archived by the owner on Apr 30, 2018. It is now read-only.

Form Validation and ngMessages Issues #283

Closed
icfantv opened this issue May 12, 2015 · 8 comments
Closed

Form Validation and ngMessages Issues #283

icfantv opened this issue May 12, 2015 · 8 comments

Comments

@icfantv
Copy link

icfantv commented May 12, 2015

I'm trying to get my head wrapped around this stuff as I've never used ngMessages before and combining it with custom validation has me out of my element. I've glued together stuff from the formly custom validation example (http://angular-formly.com/#/example/advanced/validators) and the advanced angular workshop you gave at the SLC ng-conf (I think it was called angular-formly-convert or something):

I've set this up in a plnkr: http://plnkr.co/edit/84hhADDgsLAIdU7eKsCM

First, If I uncomment the validation item, I get the following error in the console because the first item being inserted into the messages array is undefined - I'd like to be able to override the default if necessary:

TypeError: Cannot read property 'type' of undefined
    at angular-messages.js:270
    at Object.forEach (angular.js:323)
    at angular.module.directive.controller.renderMessages (angular-messages.js:269)
    at angular-messages.js:299
    at Object.$watchCollectionAction [as fn] (angular.js:14175)

My understanding from http://docs.angular-formly.com/v5.2.1/docs/formly-form is that validation.messages keys map to the default messages I've defined in my ngMessages template.

Second, the first time the form loads, if I enter an invalid pattern, and the field loses focus, the field is marked with an error, but no error message is displayed. If I refocus the field, remove the text, and lose focus again, the error messages display correctly (both the required and validation).

Third, the keys of the validators object is the name of the validator. It sounds like this can be anything so long as it's not a pre-existing validator name? (Per the Validator as an object section of the aforementioned docs page). The example the formly site uses is ipAddress but if I change my example's username to pattern, I get additional errors.

@icfantv
Copy link
Author

icfantv commented May 12, 2015

I just watched the egghead.io video on validation and it does appear that the validators object key can be anything. It doesn't explicitly state it cannot match an existing validator, but given the errors when doing so, seems like a good assumption.

Still trying to nail down the first two issues.

@kentcdodds
Copy link
Member

Sorry I haven't responded until now. Been kinda drowning recently. I'm not certain what the problem is. Why don't you have a look at this example and see if you can get it working.

@icfantv
Copy link
Author

icfantv commented May 12, 2015

No worries. Will do, thanks.

@icfantv
Copy link
Author

icfantv commented May 12, 2015

So here's something interesting with that Codementor example and I can reproduce it in a Plunker. The Chrome console is throwing an error when focus is gained and then lost on the IP Address field. Text doesn't even have to be entered.

Not sure if this is a bug in Angular or Formly, but Angular is trying to call setAttribute() on a comment tag: <!-- ngMessage: {{::name}} --> when focus is lost. The form and validation still work correctly. Adding full jQuery as a dependency makes the issue go away but it's not entirely clear why as a breakpoint on line 2887 is no longer hit using the same steps. Here's the stacktrace:

TypeError: element.setAttribute is not a function
    at forEach.attr (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:2887:15)
    at Object.JQLite.(anonymous function) [as attr] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:2986:9)
    at Object.$get.Attributes.$set (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:6829:28)
    at interpolateFnWatchAction (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:8157:28)
    at interpolateFnWatcher (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:10216:26)
    at Object.watchGroupAction (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:13980:13)
    at Object.oneTimeListener [as fn] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:12852:20)
    at Scope.$get.Scope.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:14308:29)
    at Scope.$get.Scope.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:14571:24)
    at HTMLInputElement.<anonymous> (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:23644:21)

I'll keep moving forward using the Codementor example.

@kentcdodds
Copy link
Member

Ah, the problem is actually a jqLite bug that has been fixed in 1.4.x and I don't expect will be backported to 1.3.x :-( angular/angular.js#11038

The only way to accomplish the ng-repeat with ng-messages is to use 1.4.x or include jQuery

@icfantv
Copy link
Author

icfantv commented May 12, 2015

Cool, thanks for following up on that. We're currently using (but probably don't need to be) full jQuery so that alleviates that issue.

I've been working on this problem all morning and it does not appear that, at least in my plunker setup, I can use both default messages in my validation.html file and overrides in the validation.messages object. E.g., <div class="some-message" ng-message="required">This field is required</div> and

validation: {
  messages: {
    required: function (viewValue, modelValue, scope) {
      return scope.to.label + ' is required';
    }
  }
}

If I get rid of the default messages in validation.html the values defined in validation.messages are used.

On a whim, I updated the plunker to angular 1.4 RC1 and I get a different error which actually makes sense:

Error: [$compile:nonassign] Expression 'field.model || model' used with directive 'formlyField' is non-assignable!
http://errors.angularjs.org/1.4.0-rc.1/$compile/nonassign?p0=field.model%20%7C%7C%20model&p1=formlyField
    at REGEX_STRING_REGEXP (angular.js:68)
    at $get.parentSet (angular.js:8571)
    at parentValueWatch (angular.js:8584)
    at Object.regularInterceptedExpression (angular.js:14010)
    at Scope.$get.Scope.$digest (angular.js:15403)
    at Scope.$get.Scope.$apply (angular.js:15679)
    at NgModelController.$$debounceViewValueCommit (angular.js:24748)
    at NgModelController.$setViewValue (angular.js:24720)
    at HTMLInputElement.listener (angular.js:21096)
    at HTMLInputElement.n.event.dispatch (jquery-2.1.4.min.js:3)

It appears that it's trying to bind the validation.messages.required function on my First Name field, which is not allowed per the angular error URL.

I'm ok for now in just using the default values in my validation.html file but it would be nice to be able to override them at some point. As for now, I don't have a use case to do so.

I'll wait for you to respond before closing. Thanks.

@kentcdodds
Copy link
Member

Oh, sorry, I thought you were talking about overriding messages set in the formlyValidationMessages service. Yeah, simply using the template wont work, but that's not a formly thing, that's an ng-messages thing. If you want defaults, use the formlyValidationMessages service. This is why you generally don't want to have any custom ng-message directives in there. Just the ones in the ng-repeat.

I'll have to look at making sure everything works ok in angular@1.4.x. I was under the impression that it did, but I'll double check that. Thanks!

@icfantv
Copy link
Author

icfantv commented May 12, 2015

Good deal, thanks.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants