0

Currently, I have two directives and parent controller, all on some form.

I would like to implement "related field"-like functionality. That is, data from one directive should be passed to other preferably through controller so that I have full flexibility in "routing" data between fields.

So I have this set-up:

Controller:
$scope.$watch('form.model.object', function (newValue, oldValue) {
    $scope.$broadcast("cmsRelatedChanged", {key: 'subcarriers', value: newValue['@identity']});
};

Second directive:
$scope.$on('cmsRelatedChanged', function(event, aditionalData) {
    $scope.related[aditionalData.key] = aditionalData.value;
    console.log("[CMSCollectionDirective] updated with: ", aditionalData, " event: ", event);
});

It do not work first time, when form is pre-populated with existing object But following changeds made in browser work.

As if second directive $on registered that listener after first $broadcast was made.

Additional info: Everything in second controller is done in link:, and second directive is also second in DOM.

Questions: How can I delay that first broadcast enough for $on to register listener?

EDIT: Added console.log("Adding listener") before $scope.$on, and it in fast is executed after first $broadcast, and that's why its not cough.

8
  • its very hard to understand without code. but you should be aware of the differences between $on and $emit in accordance with your directive/scopes hierarchy. maybe $emit will solve your issue Commented Oct 20, 2015 at 8:10
  • If you changed your value somewhere out of the angular context, you need to tell angular that it has been changed, by using $scope.apply() Commented Oct 20, 2015 at 8:12
  • @OriPrice I'm thinking that $on did not had chance to register listener yet, for first $broadcast. Cause after that.. It works. Commented Oct 20, 2015 at 9:16
  • @schneck $watch works every time. So just after form is pre-populated with model values, it catch change, and initial value. So its more on $on side of things that do not work. Commented Oct 20, 2015 at 9:17
  • Could you add some code samples? it will make it easier to address the issue Commented Oct 20, 2015 at 9:18

2 Answers 2

1

Maybe try to not use $broadcast and $on. For me this solution works to share data between directives:

JS:

app
    .controller('MainCtrl', function () {
        $scope.sharedData = {
            data: 1
        };

        $scope.testAction = function () {
            vm.sharedData.data++;
        }
    })
    .directive("dirFirst", function () {
        var directive = {
            link: link,
            restrict: 'AE',
            scope: {
                sharedData: '='
            }
        };
        return directive;

        function link(scope, element) {
            scope.$watch(function () {
                return scope.sharedData.data;
            }, function () {
                console.log("dirFirst: " + scope.sharedData.data)
            });

            element.on('click', function () {
                scope.sharedData.data++;
                console.log(scope.sharedData.data);
            });
        }
    })
    .directive("dirSecond", function () {
        var directive = {
            link: link,
            restrict: 'AE',
            scope: {
                sharedData: '='
            }
        };
        return directive;

        function link(scope, element) {
            scope.$watch(function () {
                return scope.sharedData.data;
            }, function () {
                console.log("dirSecond: " + scope.sharedData.data)
            });

            element.on('click', function () {
                scope.sharedData.data++;
                console.log(scope.sharedData.data);
            });
        }
    });

HTML usage:

<button dir-first shared-data="sharedData">
    Directive1
</button>
<button dir-second shared-data="sharedData">
    Directive2
</button>

<button ng-click="testAction()">ControllerAction</button>
Sign up to request clarification or add additional context in comments.

1 Comment

Would be good, but my directive already have no scope:, and if I try define one it stops working, as it have few childs that need access to some data scope: {} hides. :|
0

Biggest issue in my question ended up being order of initialization of directives and inability to use $scope as transfer medium between controller and 2nd directive.

Solution would be to use service as such medium.

Controller still register watch on 1st directive, and as soon as it gets corresponding event put received data in service.

Data availability is signalled to 2nd directive by emmiting event. However 2nd directive check availability of data in service on its own on start up.

This way 2nd directive can be initialized long after some data was sent, and still act upon it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.