0

I have a contactForm directive with template that is placed in several places. It looks something like this:

.directive('contactForm', ['SecureCheckoutService', function(SecureCheckoutService) {
    return {
        templateUrl: 'template/contactForm.html',
        replace: true,
        restrict: 'E',
        scope: {
            'modelVar': '=',
        },
        require: '^form',
        link: function (scope, element, attr, formCtrl) {
            scope.form = formCtrl;
        }
    };
}])

Directive template looks like this:

    <script type="text/ng-template" id="template/contactForm.html">
        <div>
            <div class="form-group"
                 ng-class="{ 'has-error' : form.fullname.$invalid && !form.fullname.$pristine}">
                <label class="control-label">Name *</label>
                <input class="textInput form-control" name="fullname" type="text"
                       ng-model="modelVar.fullname" ng-model-options="{ updateOn: 'blur'}" required ng-maxlength="500" update-model model="modelVar" update-data="updateData(data)" />
                <span class="completed" ng-if="form.fullname.$valid"></span>
                <span ng-show="form.fullname.$error.required && !form.fullname.$pristine"
                      style="text-align:right" class="help-block">Recipient name is required.</span>
                <span ng-show="form.fullname.$error.maxlength"
                      style="text-align:right" class="help-block">Maximum length is 500 characters.</span>
            </div>
        </div>
    </script>

And in that directive template I have another custom directive:

.directive('updateModel', ['$compile', function ($compile) {
 return {
    restrict: 'A',
    scope: {
        'updateData': '&',
        'model': '='
    },
    require: 'ngModel',
    link: function link(scope, elem, attrs, modelCtrl) {
        scope.$watch(function () { return modelCtrl.$modelValue; }, function (newValue, oldValue) {
            if (newValue != oldValue && modelCtrl.$valid){
                scope.updateData({data: scope.model});
            }
        });
    }
  };
}])

contact form directive is used like this:

<contact-form model-var="vm.model.billingInvoice" update-data="vm.updateInvoice(data)"></contact-form>

(In other places, instead of vm.updateInvoice I am using other controller functions and models)

updateData object is one of controller functions (value depends on contact-form usage, so I put it in directive scope as update-data argument. The problem is that I should propagate that function to updateModel directive and call it on model change. If I call it like this, appropriate controller function is executed, but data is undefined. So, I changed update-data argument to:

update-data="vm.updateInvoice(vm.model.billingInvoice)" and it worked! untill I tried to add contact-form directives inside ng-repeat, and than I get undefined again. I suppose it has something to do with directive scopes.

I would appreciate any help...

branko
  • 43
  • 6
  • Possible duplicate of [Angular: calling controller function inside a directive link function using &](http://stackoverflow.com/questions/16839259/angular-calling-controller-function-inside-a-directive-link-function-using) – Igor Feb 07 '17 at 13:21
  • I wouldn't say this is a duplicate. As you can see, I am using named arguments in function call. The problem is that controller function is called from nested directive. – branko Feb 07 '17 at 13:40

1 Answers1

0

Don't execute function when you pass it as a parameter. You'll have a result of its call, not the link to that function. Pass it like this: update-data="updateData"

<input class="textInput form-control" name="fullname" type="text" ng-model="modelVar.fullname" ng-model-options="{ updateOn: 'blur'}" required ng-maxlength="500" update-model model="modelVar" update-data="updateData" />"

Then, inside updateModel directive, when you call scope.updateData(), you'll have passed function as a returned value, and would be able execute it:

    var update = scope.updateData();

    scope.$watch(function () { return modelCtrl.$modelValue; }, function (newValue, oldValue) {
        if (newValue != oldValue && modelCtrl.$valid){
            update({data: scope.model});
        }
    });
TheSameSon
  • 369
  • 1
  • 9
  • Unfortunately, this solution does not work in case of nested directives. I would say both solutions are possible when invoking function from the controller according to this https://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters. But, both solutions does not work in my case. – branko Feb 08 '17 at 11:26