4

I am using http request to get data from json file which I than use in controller.

    app.controller('mainCtrl', ['$scope', 'loaderService', function ($scope, loaderService) {
   //gets data from service 
        loaderService.getLoadedHtml().then(function (result) {
            $scope.fields = result.data;
        });
    }]);

I need to update directive when this $scope.fields change as

app.directive('dform', function () {
    return {
        scope: {
            action: '@',
            method: '@',
            html: '='
        },
        link: function (scope, elm, attrs) {
            var config = {
                "html": scope.fields
            };

            scope.$watch('fields', function (val) {
                elm.dform(config);
            });

            //console.log(config);
            //elm.dform(config);
        }
    };
})

and here is how I am using this directive

<div html="fields" dform></div>

But in my case when $scope.fields changes, i get scope as undefined in my directive $watch function.

Question:

How can I get the updated value for scope.fields in scope.$watch function?

CodeGenius
  • 514
  • 1
  • 6
  • 21

3 Answers3

2

You need to give the directive access to fields by adding a binding for it:

scope: {
  action: '@',
  method: '@',
  html: '=',
  fields: '='
}

And HTML:

<dform fields="fields" ...

The value might be undefined the first time, then you don't want to call dform:

scope.$watch('fields', function(newValue, oldValue) {

  if (newValue === oldValue) return;

  var config = {
    "html": newValue
  };

  elm.dform(config);
});

Update

With this HTML:

<div html="fields" dform></div>

You just need to watch html instead, no need for $parent or adding fields as a binding:

scope.$watch('html', ...
tasseKATT
  • 38,470
  • 8
  • 84
  • 65
1

Usually for directives that should be as transparent as possible, no new scope is supposed be used. Having a new scope also prevents other directives from requesting a new scope on the same element.

If only one of the attributes is supposed to be dynamic, it is as simple as

scope: false,
link: function (scope, elm, attrs) {
    scope.$watch(function () { return scope[attrs.html] }, function (val) {
        if (val === undefined) return;

        var config = {
            action: attrs.action,
            method: attrs.method,
            html: val
        };

        elm.dform(config);
    });

}

Alternatively, bindToController can be used in more modern, future-proof fashion (depending on what happens with html, $scope.$watch can be further upgraded to self.$onChanges hook).

scope: true,
bindToController: {
    action: '@',
    method: '@',
    html: '='
},
controller: function ($scope, $element) {
    var self = this;

    $scope.$watch(function () { return self.html }, function (val) {
        if (val === undefined) return;

        var config = {
            action: attrs.action,
            method: attrs.method,
            html: val
        };

        $element.dform(config);
    });
}

Considering that html="fields", the code above will watch for fields scope property.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
0

use $parent.fields instead of fields

  • @Umar Using $parent in a directive with isolated scope is antipattern. – Estus Flask Dec 26 '16 at 13:04
  • @estus Thank you for the suggestion. Yes its against pattern, but I am in situation where I cannot use any workaround than this. – CodeGenius Dec 26 '16 at 13:05
  • @Umar See the other answer, that's the correct one. It isn't obvious from your question why it isn't applicable here. – Estus Flask Dec 26 '16 at 13:08
  • @estus Actually it is a jquery plugin. Here is it's full demonstration. http://stackoverflow.com/questions/41323138/jquery-function-converted-to-directive-not-working-in-angular/ I just need fields. so html is extra here for me. – CodeGenius Dec 26 '16 at 13:10
  • @Umar In this case I would suggest to use `bindToController` instead of isolated scope (like it is shown here http://stackoverflow.com/a/31415287/3731501). It allows to maintain proper scope hierarchy while still having bindings. – Estus Flask Dec 26 '16 at 13:16
  • @estus I am not very good at angular, can you please post code for my case? – CodeGenius Dec 26 '16 at 13:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131514/discussion-between-umar-and-estus). – CodeGenius Dec 26 '16 at 13:36