Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding ngModel to input with a directive

I have an input element and I would like to bind a ngModel and a ngClass to it using a custom directive, but I'm having some troubles.

What I have:

<input type="text" myDirective="PropertyFromScope" />

What I want as result:

<input type="text" ng-model="PropertyFromScope" ng-class="{'class' : MethodFromScope}" />

I'm trying to avoid using templates, because I want the directive to work with any input tag.

Here's what I got so far:

angular.module('customDirectives', [])
.directive('myDirective', function () {
    var linker = function (scope, element, attrs) {
        attrs.$set('ngModel', attrs.myDirective);
        attrs.$set('ngClass', '{\'class\' : MethodFromScope}');
    }
    return {
        restrict: 'A',        
        link: linker
    }
});

Here's a JSFiddle: http://jsfiddle.net/Q8QJJ/

like image 958
André Lourenço Avatar asked Jul 01 '13 13:07

André Lourenço


People also ask

Is ngModel a directive?

The ngModel directive is a directive that is used to bind the values of the HTML controls (input, select, and textarea) or any custom form controls, and stores the required user value in a variable and we can use that variable whenever we require that value. It also is used during form validations.

What does [( ngModel )] does in Angular?

AngularJS ng-model Directive The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.

What should I import into ngModel?

The ngmodel directive is not part of the Angular Core library. It is part of the FormsModule library. You need to import the FormsModule package into your Angular module.


2 Answers

Are you trying to accomplish this ?

Pretty simple solution:

myApp.directive('myDirective', function ($compile) {
    return {
        restrict: 'A',        
        compile: function(element, attrs) {
            element.attr('ng-model', attrs.myDirective);
            element.removeAttr("my-directive");
            element.attr('ng-class', '{\'class\' : testFunction()}');
            return {
               pre: function preLink(scope, iElement, iAttrs, controller) { },
               post: function postLink(scope, iElement, iAttrs, controller) { 
                 $compile(iElement)(scope);
               }
            }
        }
    }
});

Here is a fiddle http://jsfiddle.net/V9e9M/

like image 163
Nix Avatar answered Oct 20 '22 07:10

Nix


I was unable to get this to work in a compile function (it added the attributes, but it did not seem to notice them). However, this linking function seems to work:

myApp.directive('myDirective', function ($compile) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var wrappedElement = angular.element(
                '<input type="' + attrs.type + '" ng-model="' 
                 + attrs.myDirective + '">');
            element.replaceWith(wrappedElement);
            $compile(wrappedElement)(scope);
        }
    }
});

Fiddle

Note: I forgot to add ng-class, but I assume if ng-model works, ng-class should work.

Update:

Here's a version that uses a compile function:

myApp.directive('myDirective', function () {
    return {
        restrict: 'A',
        compile: function (tElement, tAttrs) {
            // for some unknown-to-me reason, the input must
            // be wrapped in a span or div:
            var tplElement = angular.element('<span><input></span>');
            var inputEl = tplElement.find('input');
            inputEl.attr('type', tAttrs.type);
            inputEl.attr('ng-model', tAttrs.myDirective);
            tElement.replaceWith(tplElement);
        }
    };
});

Fiddle

like image 2
Mark Rajcok Avatar answered Oct 20 '22 06:10

Mark Rajcok