5

My ngMessages doesnt work inside my directives template!

I have a directive myInput with a template and a link function, inside the template function I create template string for a wrapped <label> and <input>.

Inside the Link function I use the require: '^form' FormController and retrieve the form name. Then I'm putting a ngMessages block after the wrapped elements.

    (function () {
        'use strict';

        angular
            .module('app.components')
            .directive('myInput', MyInput);

        /*@ngInject*/
        function MyInput($compile, ValidatorService, _, LIST_OF_VALIDATORS) {
            return {
                require: '^form',
                restrict: 'E',
                controller: MyInputController,
                controllerAs: 'vm',
                bindToController: true,
                template: TemplateFunction,
                scope: {
                    label: '@',
                    id: '@',
                    value: '=',
                    validateCustom: '&'
                },
                 link: MyInputLink

            };

            function MyInputController($attrs) {
                var vm = this;
                vm.value = '';
                vm.validateClass = '';
                vm.successMessage = '';
                vm.errorMessage = '';
            }

            function TemplateFunction(tElement, tAttrs) {
                return '<div class="input-field">' +
                    '   <label id="input_{{vm.id}}_label" for="input_{{vm.id}}" >{{vm.label}}</label>' +
                    '   <input id="input_{{vm.id}}" name="{{vm.id}}" ng-class="vm.validateClass" type="text" ng-model="vm.value" >' +
                    '</div>';

            }

            function MyInputLink(scope, element, attrs, form){
                var extra = '   <div ng-messages="' + form.$name + '.' + scope.vm.id + '.$error">' +
                    '       <div ng-messages-include="/modules/components/validationMessages.html"></div>' +
                    '   </div>';
                $(element).after(extra);
            }
        }
    })();

Usage:

    <h1>Test</h1>
    <form name="myForm">
        <my-input label="My Input" id="input1" value="vm.input1"></my-input>

        -------

        <!-- this block is hardcoded and is working, it does not come from the directive! -->
        <div ng-messages="myForm.input1.$error">
            <div ng-messages-include="/modules/components/validationMessages.html"></div>
        </div>

    </form>
Lusk116
  • 791
  • 1
  • 6
  • 17

2 Answers2

0

Instead of adding the ngMessages block inside the link function, add it inside the compile function.

It is not as handy as in the link funciton because of the missing FormController, but it works :-)

Here the code:

    compile: function(tElement, tAttrs){
        var name = tElement.closest('form').attr('name'),
                   fullFieldName = name + '.' + tAttrs.id; // or tAttrs.name
        var extra = '<div ng-messages="' + fullFieldName + '.$error">' +
                    '    <div ng-messages-include="/modules/components/validationMessages.html"></div>' +
                    '</div>';
        $(element).after(extra);
Lusk116
  • 791
  • 1
  • 6
  • 17
  • 1
    Would you be able to add the full code or maybe create a plnkr ? I have the very same problem and I can't seem to fix it ! – keithm Jan 14 '16 at 14:44
0

Here is what I did, I added to scope, myForm: '=' then in the directive's template referred to <div ng-messages="vm.myForm[vm.id].$error" >

I feel this is much cleaner than mucking around in the link function.

Nicholas Marshall
  • 2,981
  • 2
  • 26
  • 22
  • 1
    I wanted to add as few attributes as possible. and adding the same attribute with the same value over and over again, imagine a form with up to 25 inputs ( o yeah, requirements....), is something I don't want. That's the reason I used the compile function + adding a check if a form tag is present or not. – Lusk116 Jul 29 '15 at 21:51