1

I'm using Paul Yoder's angular-bootstrap-show-errors directive to cleverly toggle the 'has-error' class on my form-groups. This works great except when the content of my form group includes a directive that uses a template to render its input, like a typeahead. The relevant code is here:

angular.module('ui.bootstrap.showErrors', [])
    .directive 'showErrors', ['$timeout', ($timeout) ->
        linkFn = (scope, el, attrs, formCtrl) ->
        blurred = false
        inputEl = el[0].querySelector("[name]")
        inputNgEl = angular.element(inputEl)
        inputName = inputNgEl.attr('name')
        unless inputName
           throw "show-errors element has no child input elements with a 'name' attribute"

       inputNgEl.bind 'blur', ->
           blurred = true
           el.toggleClass 'has-error', formCtrl[inputName].$invalid
       scope.$watch ->
           formCtrl[inputName].$invalid
           , (invalid) ->
              return if !blurred && invalid
              el.toggleClass 'has-error', invalid

       scope.$on 'show-errors-check-validity', ->
           el.toggleClass 'has-error', formCtrl[inputName].$invalid
       scope.$on 'show-errors-reset', ->
           $timeout ->
               # want to run this after the current digest cycle
               el.removeClass 'has-error'
               blurred = false
               , 0, false
    {
        restrict: 'A'
        require: '^form'
        compile: (elem, attrs) ->
        unless elem.hasClass 'form-group'
            throw "show-errors element does not have the 'form-group' class"
        linkFn
    }
]

And my sample form looks like this:

<div class="form-group" show-errors>
    <cool-control />
</div>

This error always gets thrown because when the code is evaluated, the input element doesn't exist yet. Is there a way I can change the timing of this selection or re-evaluate it after the child directive gets done rendering?

Joshua Barron
  • 1,532
  • 2
  • 26
  • 42
  • Not strictly your answer, but google lead me here. I was trying to use `show-errors` in a directive that was placed several times on the page. The trick was to use `ng-form` directive - see http://stackoverflow.com/a/14379763/1141876 – fiat Aug 06 '15 at 00:13

1 Answers1

1

Ultimately the solution was to use the $timeout function to wrap my link method for the directive, ensuring that event binding was occurring after the DOM had rendered.

As a warning for people who come across this question, at the time of this answer there was a subtle bug in Angular involving remotely loaded directive templates not being rendered before the link function executes. See this question for more information: Why is the post link function executed before the transcluded child link functions?

Community
  • 1
  • 1
Joshua Barron
  • 1,532
  • 2
  • 26
  • 42