Commit 63a4ab59 authored by Randall Leeds's avatar Randall Leeds

Simplify form error input handling

The form-input class now has the directive responsible for setting
the error classes. It watches its scope and sets the errors only
if the model is defined or pristine. This guard keeps the error class
from being set until validation passes (when the model becomes defined)
and keeps it from being cleared until the pristine state is reset.

The form-validate directive is now just a controller for form-input to
register with. It sets all fields to dirty and forces a render on
submit.

These mechanisms are better all around than trying to listen for a the
model to be undefined and setting pristine automatically. The model is
undefined whenever validation is failing. There are times when the from
should maybe be cleared but still show errors. Now, it is left up to
other code to set pristine if the form should be reset.
parent 5b433736
...@@ -79,15 +79,13 @@ authDirective = ['$timeout', ($timeout) -> ...@@ -79,15 +79,13 @@ authDirective = ['$timeout', ($timeout) ->
scope.onError() scope.onError()
scope.$on 'success', (event) -> scope.$on 'success', (event) ->
form.$setPristine()
scope.onSuccess() scope.onSuccess()
scope.$on 'timeout', (event) -> scope.$on 'timeout', (event) ->
form.$setPristine()
scope.onTimeout() scope.onTimeout()
scope.$watch 'model', (value) ->
if value is null
form.$setPristine()
scope.$watch 'tab', (name) -> scope.$watch 'tab', (name) ->
$timeout -> $timeout ->
elem elem
......
formValidate = ['$timeout', ($timeout) -> formInput = ->
link: (scope, elem, attr, form) -> link: (scope, elem, attr, [form, model, validator]) ->
isSubmitted = false return unless form?.$name and model?.$name and validator
fieldClassName = 'form-field' fieldClassName = 'form-field'
errorClassName = 'form-field-error' errorClassName = 'form-field-error'
toggleClass = (field, {addClass}) -> render = model.$render
inputEl = elem.find("[name=#{field.$name}]")
fieldEl = inputEl.parents(".#{fieldClassName}").first()
fieldEl.toggleClass(errorClassName, addClass)
updateField = (field) -> resetResponse = (value) ->
return unless field? model.$setValidity('response', true)
value
if field.$valid or field.$pristine toggleClass = (addClass) ->
toggleClass(field, addClass: false) elem.toggleClass(errorClassName, addClass)
else if field.$dirty elem.parent().toggleClass(errorClassName, addClass)
toggleClass(field, addClass: true)
# A custom parser for each form field that is used to reset the "response" model.$parsers.unshift(resetResponse)
# error state whenever the $viewValue changes. model.$render = ->
fieldParser = (field, value) -> toggleClass(model.$invalid and model.$dirty)
field.$setValidity('response', true) render()
updateField(field) if field.$valid
return value
forEachField = (fn) -> validator.addControl(model)
fn(field) for own _, field of form when field?.$name? scope.$on '$destroy', -> validator.removeControl this
forEachField (field) -> scope.$watch ->
parser = angular.bind(null, fieldParser, field) if model.$modelValue? or model.$pristine
field.$parsers.push(parser) model.$render()
return
# Validate field when the content changes. require: ['^?form', '?ngModel', '^?formValidate']
elem.on 'change', ':input', -> restrict: 'C'
forEachField(updateField)
# Validate form on submit and set flag for error watcher.
elem.on 'submit', ->
isSubmitted = true
forEachField (field) ->
field.$setViewValue(field.$viewValue)
updateField(field)
scope.$watch form.$name + '.$error', -> formValidate = ->
if isSubmitted controller: ->
forEachField(updateField) controls = {}
isSubmitted = false
, true
scope.$watch form.$name + '.$pristine', (value) -> addControl: (control) ->
forEachField(updateField) if value is true if control.$name
controls[control.$name] = control
require: 'form' removeControl: (control) ->
] if control.$name
delete controls[control.$name]
submit: ->
# make all the controls dirty and re-render them
for _, control of controls
control.$setViewValue(control.$viewValue)
control.$render()
link: (scope, elem, attr, ctrl) ->
elem.on 'submit', ->
ctrl.submit()
markdown = ['$filter', '$timeout', ($filter, $timeout) -> markdown = ['$filter', '$timeout', ($filter, $timeout) ->
...@@ -378,6 +378,7 @@ match = -> ...@@ -378,6 +378,7 @@ match = ->
angular.module('h.directives', ['ngSanitize', 'ngTagsInput']) angular.module('h.directives', ['ngSanitize', 'ngTagsInput'])
.directive('formInput', formInput)
.directive('formValidate', formValidate) .directive('formValidate', formValidate)
.directive('fuzzytime', fuzzytime) .directive('fuzzytime', fuzzytime)
.directive('markdown', markdown) .directive('markdown', markdown)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment