0
votes

Edit: I have added the details as well.

I could do with some help with passing the value selected in my directive to my controller $scope.

I have a very basic directive that I want to place within another directive, but the value does not get passed to the controller scope. I get an "undefined" value for my parameter.

However, when I place the little directive anywhere in the view's HTML, and not within the other directive's tags, it works.

This is my new directive:

(function () {
    'use strict';

    angular.module('portalDashboardApp')
      .directive('ogItemsPerPage', function () {
          return {
              restrict: 'E',
              replace: true,
              templateUrl: './tpls/ItemsPerPageTemplate.html',
              scope: {
                  perPageCountOptions: [30, 50, 100, "ALL"],
                  selectedItemsPerPage: '@'
              }
          };
      });
})();

This is the template:

<div>
    <div id="DropDownBox">
        <label for="ItemsPerpage">Items per Page: </label>
        <select ng-change="changePageCount()" ng-model="selectedItemsPerPage" id="ItemsPerpage" ng-options="perPage for perPage in perPageCountOptions"></select>
    </div>
</div>

This is the function called in my controller:

$scope.changePageCount = function () {

    if ($scope.selectedItemsPerPage === "ALL") {
        $scope.perPageCount = -1;
    }
    else {
        $scope.perPageCount = $scope.selectedItemsPerPage;
    }
    pullSocialData();
}

This is the view where I am placing my <og-items-per-page> directive, inside the tags of another directive:

<og-data-box heading="Tweet List" link="" uid="socialMentionsMeta" description="">
    <div class="dataStatus">
        {{dataStatus}}
        <og-loading-indicator></og-loading-indicator>
    </div>
    <og-items-per-page></og-items-per-page>
    <div class="dataContent" ng-show="dataContent" ng-mouseover="showGraphTrainingInfo()">
        <og-social-media-mentions-list></og-social-media-mentions-list>

        <div ng-show="showMorePostLoading" id="morePostLoadingContainer"><div id="morePostLoadingInner"></div></div>
    </div>
</og-data-box>

The data-box directive:

(function () {
    'use strict';

    angular.module('portalDashboardApp')
        .directive('ogDataBox', function () {
            return {
                restrict: 'E',
                transclude: true,
                replace: true,
                scope: {
                    heading: '@',
                    link: '@',
                    uid: '@',
                    description: '@',
                    chartConfig: '@'
                },
                link: function (scope) {

                    scope.boxOpenCloseTitle = 'Collapse';
                    scope.iconStatus = 'upIcon';
                    scope.contentStatus = '';
                    var openCloseStatus = true;
                    var maximumSize = false;
                    scope.dataBoxUnderlayClass = '';
                    scope.dataBoxMaxMinClass = '';
                    scope.maxMinIcon = 'maximise';

                    scope.openCloseDataBox = function () {
                        if (openCloseStatus) {
                            scope.boxOpenCloseTitle = 'Expand';
                            openCloseStatus = false;
                            scope.iconStatus = 'downIcon';
                            scope.contentStatus = 'hideContent';
                        }
                        else {
                            scope.boxOpenCloseTitle = 'Collapse';
                            openCloseStatus = true;
                            scope.iconStatus = 'upIcon';
                            scope.contentStatus = '';
                        }
                    };

                    scope.maxMinDatabox = function () {

                        maximumSize = !maximumSize;

                        if (maximumSize) {
                            scope.dataBoxUnderlayClass = 'dataBoxUnderlayFullScreen';
                            scope.dataBoxMaxMinClass = 'dataBoxMaximised';
                            scope.maxMinIcon = 'minimise';
                        }
                        else {
                            scope.dataBoxUnderlayClass = '';
                            scope.dataBoxMaxMinClass = '';
                            scope.maxMinIcon = 'maximise';
                        }

                    };

                },
                templateUrl: './tpls/DataBoxTemplate.html'
            };
        });
})();

The data-box template:

<div ng-class="dataBoxUnderlayClass">
    <section class="dataBox" id="{{uid}}" ng-class="dataBoxMaxMinClass">
        <header class="dataBoxHeader">
            {{heading}}
            <img src="images/openCloseIcon.svg" title="{{boxOpenCloseTitle}}" width="15" height="15" class="openCloseBox {{iconStatus}}" ng-click="openCloseDataBox()" />
            <img ng-mouseover="infoIconStyle='dataBoxInfoContentShow'" ng-mouseleave="infoIconStyle='dataBoxInfoContentHide'" src="images/info-icon.svg" height="15" class="dataBoxInfo" />
        </header>
        <div class="dataBoxContent {{contentStatus}}">
            <div ng-class="infoIconStyle" class="dataBoxInfoContent">{{description}}</div>
            <div ng-transclude></div>
        </div>
    </section>
</div>

What do I need to change so that I can nest my directive within other directives if I want to?

Thank you!

1
Can you add the og-data-box definition ? - Tako
I have posted the update. thank you! - onmyway
See my comment below - Tako

1 Answers

0
votes

The problem comes from the isolated scope created by your directive.

The html inside og-data-box is under the directive scope and can't access to the controller scope.

As it is describe in this article http://angular-tips.com/blog/2014/03/transclusion-and-scopes/ if you want to access your controller scope inside <og-data-box></og-data-box> you need to append it to your isolated scope.

Something like that should correct your problem

app.directive('og-data-box', function() {
  return {
    restrict: 'EA',
    scope: {
      heading: '=',
      link: '=',
      uid: '=',
      description: '='
    },
    transclude:true,
    link: function(scope, element, attrs, ctrl, transclude) {
      transclude(scope.$parent, function(clone, scope) {
        element.append(clone);
      });
    }
  };
});

EDIT : As it is mentioned in the comment this is not the best way to do it.

You should pass your scope to the scope of og-data-box then you can use it in the nested directive :

og-data-box (I add selectedItemsPerPage to the scope)

(function () {
'use strict';

angular.module('portalDashboardApp')
    .directive('ogDataBox', function () {
        return {
            restrict: 'E',
            transclude: true,
            replace: true,
            scope: {
                heading: '@',
                link: '@',
                uid: '@',
                description: '@',
                chartConfig: '@',
                selectedItemsPerPage: '@'
            },
            link: function (scope) {

                scope.boxOpenCloseTitle = 'Collapse';
                scope.iconStatus = 'upIcon';
                scope.contentStatus = '';
                var openCloseStatus = true;
                var maximumSize = false;
                scope.dataBoxUnderlayClass = '';
                scope.dataBoxMaxMinClass = '';
                scope.maxMinIcon = 'maximise';

                scope.openCloseDataBox = function () {
                    if (openCloseStatus) {
                        scope.boxOpenCloseTitle = 'Expand';
                        openCloseStatus = false;
                        scope.iconStatus = 'downIcon';
                        scope.contentStatus = 'hideContent';
                    }
                    else {
                        scope.boxOpenCloseTitle = 'Collapse';
                        openCloseStatus = true;
                        scope.iconStatus = 'upIcon';
                        scope.contentStatus = '';
                    }
                };

                scope.maxMinDatabox = function () {

                    maximumSize = !maximumSize;

                    if (maximumSize) {
                        scope.dataBoxUnderlayClass = 'dataBoxUnderlayFullScreen';
                        scope.dataBoxMaxMinClass = 'dataBoxMaximised';
                        scope.maxMinIcon = 'minimise';
                    }
                    else {
                        scope.dataBoxUnderlayClass = '';
                        scope.dataBoxMaxMinClass = '';
                        scope.maxMinIcon = 'maximise';
                    }

                };

            },
            templateUrl: './tpls/DataBoxTemplate.html'
        };
    });
})();

And then when you call all the directive :

<og-data-box heading="Tweet List" link="" uid="socialMentionsMeta" description=""     selected-items-per-page="selectedItemsPerPage">
    <div class="dataStatus">
        {{dataStatus}}
        <og-loading-indicator></og-loading-indicator>
    </div>
    <og-items-per-page selected-items-per-page="selectedItemsPerPage"></og-items-per-page>
    <div class="dataContent" ng-show="dataContent" ng-mouseover="showGraphTrainingInfo()">
        <og-social-media-mentions-list></og-social-media-mentions-list>

        <div ng-show="showMorePostLoading" id="morePostLoadingContainer"><div id="morePostLoadingInner"></div></div>
    </div>
</og-data-box>