Joe.wang
Joe.wang

Reputation: 11793

ngModel doesn't work in the custom directive

I knew definitely it is problem I didn't understand the scope of AngularJs well. I had to committed it is hard for me. So I post a example here, Hope someone help me to get it more clear. Thanks.

Html Part

<test-Area ng-model="testModel.text"></test-Area>
<input type="text" ng-model="testModel.text"></input>
<textarea ng-model="testModel.text"></textarea>

JS Part

app.controller('AppController', function ($scope, $log) {
    $scope.testModel={text:"123"};
})

app.directive('testArea',function() {
    var textareaInputDir = {};
    textareaInputDir.restrict="E";
    textareaInputDir.replace="true";
    textareaInputDir.template="<div><textarea ></textarea><label><small></small><span >*</span></label></div>";
    textareaInputDir.require="ngModel";
    textareaInputDir.link=function (scope, jqElement, attrs,ngModelCtrl) {
        scope.backgroundValue={text:''};
        ngModelCtrl.$render = function () {
            jqElement.find('textarea').text(ngModelCtrl.$viewValue);
            scope.backgroundValue.text=ngModelCtrl.$viewValue;
        }
        //get the textarea element
        var txtAreaElement = jqElement.find('textarea');
        //listen for the change event

        txtAreaElement.bind('keyup', function(){
            if (scope.$$phase) return;
            scope.$apply(function () {
                var bgVal=angular.isString(ngModelCtrl.$viewValue) ? ngModelCtrl.$viewValue : '';
                scope.backgroundValue.text=bgVal;
                ngModelCtrl.$setViewValue(bgVal);
            });

        });
        scope.$watch('backgroundValue.text',function()
        {
            ngModelCtrl.$setViewValue(scope.backgroundValue.text)
        });
    };
    return textareaInputDir;
});

Please review what I had done so far in the fiddle.

I was trying to implement a two ways binding for my directive testArea and others. But I can't figure out why it doesn't work in my directive?

Updated

I changed the code a little bit. but still have problem. if I changed the value of text area. the 2 ways binding will be lost...

txtAreaElement.bind('keyup', function(){
            if (scope.$$phase) return;
            scope.$apply(function () {
                var txtAreaElement = jqElement.find('textarea');        
                var bgVal=txtAreaElement[0].value;
                scope.backgroundValue.text=bgVal;
                ngModelCtrl.$setViewValue(bgVal);

            });

        });

Upvotes: 0

Views: 623

Answers (2)

Narek Mamikonyan
Narek Mamikonyan

Reputation: 4611

You must set up ng-model not on you directeve, you need to set it on textarea element

check example

In your way you are applying to directive template element which is starting with <div>.

Upvotes: 2

Joe.wang
Joe.wang

Reputation: 11793

I found if I want to apply bi-directional binding. It doesn't need to use NgModelController. according to this tutorial.

Please review below.

HTML

<test-Area ng-model="testModel.text"></test-Area>

js

app.directive('testArea',function() {
    var textareaInputDir = {};
    textareaInputDir.restrict="E";
    textareaInputDir.replace="true";
    textareaInputDir.scope={ngModel:'='};
    textareaInputDir.template="<div><textarea ng-model='ngModel'></textarea><label><small></small><span >*</span></label></div>";

    return textareaInputDir;
});

If there is something wrong. please kindly correct me .thanks.

Upvotes: 0

Related Questions