Joe.wang
Joe.wang

Reputation: 11791

Writing custom event for custom directive

I am trying to implement a custom directive textareaInput. but I didn't know how implement the custom event for the directive.

The code looks like below.

myApp.directive('textareaInput',function() {
    var textareaInputDir = {};
    textareaInputDir.restrict="E";
    textareaInputDir.replace="true";
    textareaInputDir.templateUrl="../../../views/widget/textarea/textarea-template.html";
    textareaInputDir.scope={};
    textareaInputDir.link=function (scope, jqElement, attrs) {
        scope.elementDefinition={};
        scope.elementDefinition.label=attrs.label;
        scope.elementDefinition.isShow=attrs.isshow;
        scope.elementDefinition.isRequired=attrs.isrequired;
        scope.elementDefinition.isDisabled=(attrs.isdisabled === "true");
        scope.elementDefinition.defaultValue=attrs.defaultvalue;
        scope.keyValue={text:scope.elementDefinition.defaultValue};

    };

    return textareaInputDir;
});

The template html looks like:

<div>
    <textarea ></textarea>
    <label>
        <small></small>
        <span >*</span>
    </label>
</div>

In the view I will use it like below. In below example. I tried to add a ng-change event for my directive. and I want to define the someMethod in the controller testCtrl .but found this event will be attached for the root element of template(it is a div). So it will doesn't make sense .because when the text changed in the textarea , the root element can't know it. So I want all the events defined in the directive like ng-change, ng-click etc can be attached to the child element textarea of template. Is there any way to make it ? thanks.

<form  ng-controller='testCtrl'>
    <textarea-Input label="Project Description" isShow="true" 
    isRequired="true" isDisabled="false" ng-change="someMethod()" ng-click="someClick()"></textarea-Input>

</form>

Upvotes: 0

Views: 750

Answers (2)

Bolza
Bolza

Reputation: 1944

First you have to get the onChange passed function by making it a scope variable. You could also decide to change the name of the event like "inputChange" to avoid confusion. Then just get the textarea element and bind the callback to it's change event.

myApp.directive('textareaInput',function() {
    var textareaInputDir = {};
    textareaInputDir.restrict="E";
    textareaInputDir.replace="true";
    textareaInputDir.templateUrl="../../../views/widget/textarea/textarea-template.html";
    textareaInputDir.scope= {
        //isolated scope event, better change name anyway
        ngChange: '&' 
    };
    textareaInputDir.link=function (scope, jqElement, attrs) {
        scope.elementDefinition={};
        scope.elementDefinition.label=attrs.label;
        scope.elementDefinition.isShow=attrs.isshow;
        scope.elementDefinition.isRequired=attrs.isrequired;
        scope.elementDefinition.isDisabled=(attrs.isdisabled === "true");
        scope.elementDefinition.defaultValue=attrs.defaultvalue;
        scope.keyValue={text:scope.elementDefinition.defaultValue};

        //get the textarea element
        var inputElement = jqElement.find('textarea');
        //listen for the change event
        inputElement.bind('change', scope.ngChange);

    };

    return textareaInputDir;
});

This should be enough to see it working

Upvotes: 0

Fabio Milheiro
Fabio Milheiro

Reputation: 8474

Although I haven't tried this myself I believe you have a scope problem.

You need to use transclude: true in your directive definition and then use the ng-change="someMethod()" inside your text area template as your textarea-input template could include many elements capable of firing a change event. Is your ng-change attribute capture all of them?

For more info look for this "Creating a Directive that Wraps Other Elements" in this long page of Angular JS docs.

This answer will shed some light about Angular JS directive scope issue.

Upvotes: 1

Related Questions