Tomer
Tomer

Reputation: 17940

after upgrading to Angular 1.4 my directive breaks

I have a form directive that injects some bootstrap classes and adds ng-messages to a form. Once i upgraded to angular 1.4 it breaks.

I was able to pinpoint the problem to this method:

var setupDom = function ( element ) {
        var input = element.querySelector( 'input,textarea,select' );
        var label = element.querySelector( 'label' );
        var type = input.getAttribute( 'type' );
        var name = input.getAttribute( 'name' );
        //checkbox and radio need a different class
        if ( type !== 'checkbox' && type !== 'radio' ) {
            input.classList.add( 'form-control' );
        }
        element.classList.add( 'form-group' );
        return name;
    };

The html element that this code runs on looks like this:

<input type="url" name="{{'videoLink' + $index}}" id="{{'videoLink' + $index}}"
                       ng-model="item.videoLink" placeholder="Youtube or Vimeo video link"/>

The problem is in var name, since it gets the non-compiled version {{'videoLink' + $index}} instead of videoLink0 , videoLink1... as it used to in 1.3.

Any idea why is it happening and how to overcome this problem?

UPDATE:

here is the entire directive code:

'use strict';
(function ( module ) {
    var setupDom = function ( element, scope ) {
        var input = element.querySelector( 'input,textarea,select' );
        var label = element.querySelector( 'label' );
        var type = input.getAttribute( 'type' );

        var name = scope.$eval(input.getAttribute( 'name' ));
        //checkbox and radio need a different class
        if ( type !== 'checkbox' && type !== 'radio' ) {
            input.classList.add( 'form-control' );
        }
        element.classList.add( 'form-group' );
        return name;
    };
    var addMessages = function ( form , element , name , $compile , scope ) {
        var messages = '<div class="help-block am-fade-and-scale" ' + 'ng-messages=" ' + form.$name + '.' + name + '.$error' + '" ' + 'ng-show="' + form.$name + '.' + name + '.$dirty">' + '<div ng-messages-include="/assets/angular-client/app/html/common/forms/message.html"></div></div>';
        element.append( $compile( messages )( scope ) );
    };
    var watcherFor = function ( form , name ) {
        return function () {
            if ( name && form[ name ] ) {
                return form[ name ].$invalid;
            }
        };
    };
    var updaterFor = function ( element ) {
        return function ( hasError ) {
            if ( hasError ) {
                element.removeClass( 'vl-success' ).addClass( 'vl-error' );
            } else {
                element.removeClass( 'vl-error' ).addClass( 'vl-success' );
            }
        };
    };
    var link = function ( $compile ) {
        return function ( scope , element , attr , formCtrl ) {
            var name = setupDom( element[ 0 ] ,scope );
            addMessages( formCtrl , element , name , $compile , scope );
            scope.$watch( watcherFor( formCtrl , name ) , updaterFor( element ) );
        };
    };
    var forminput = /*ngInject*/
        function ( $compile ) {
            return {
                restrict : 'A' ,
                require :  '^form' ,
                link :     link( $compile )
            };
        };
    forminput.$inject = [ '$compile' ];
    module.directive( 'vlForminput' , forminput );
}( angular.module( 'html.common' ) ));

Upvotes: 2

Views: 108

Answers (2)

Kimberly
Kimberly

Reputation: 11

I encountered the same issue and addressed it using the replace method.

HTML:

<input type="text" ng-model="carrierBillingRateException.rate" name="rate{{$index}}" required />

Angular Directive:

var setupDOM = function (element, scope) {
    var input = element[0].querySelector("input, textarea, select");
    var type = input.getAttribute("type");
    var name = input.getAttribute("name").replace('{{$index}}', scope.$index);

    return name;
};

Upvotes: 1

BobDoleForPresident
BobDoleForPresident

Reputation: 552

Why not try using something like the following:

var app = angular.module('html.common', []);
app.directive('vlFormInput', function () {
    return {
        restrict: 'EA',
        templateUrl: 'path/to/html/file/with/ng-repeat.html',
        link: {
        post: function(scope,elem,attr){
              scope.setUpDom = function(){
              var input = angular.element( 'input,textarea,select' );
              var label = angular.element( 'label' );
              var type = input.getAttribute( 'type' );
              var name = input.getAttribute( 'name' );
              }

         }    
       }
    };
});

I honestly have not tested this code but it should point you in the right direction. By using a post: function the values should be compiled when you go looking for them.

Upvotes: 0

Related Questions