Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

execute/render a directive from another directive

I have following 2 directives. In DirectiveA I am getting some data from remote server and then rendering a template with that data as anchor tag. Now when user click on any of the link, I broadcast event and listen to that event in DirectiveB. In DirectiveB I want to make another ajax request and when I receive response with data then I want to render DirectiveB template. My current approach does not work because it executes both of the Directives in the beginning and at that time I do not have any data for DirectiveB. Below is the code

DirectiveA

angular.module('app').directive('DirectiveA', function ($http) {
    'use strict';

    return {
        restrict: 'E',
        templateUrl: '/templates/templateA.html',
        controller: function ($scope) {
            $scope.showDetails = function (num) { // <-- this executes in ng-click in template
                $scope.$broadcast('season', num);
            };
        },

        link: function (scope, element, attributes) {
            $http.get(attributes.resource).then(function (response) {
                scope.rows = response.data;
                scope.seasons = [];

                for (var i = 0; i < scope.rows.length; i++) {
                    var num = parseInt(scope.rows[i].data);

                    if (year >= 2005 && year <= 2015) {
                        scope.seasons.push({ 'data': scope.rows[i].data });
                    }
                }
            });
        }
    };
});

Here is DirectiveB

angular.module('app').directive('DirectiveB', function() {
    return {
        restrict: 'E',
        templateUrl: 'templates/templateB.html',
        controller: function($scope, $http) {
            $scope.$on('season', function ($scope, num) { // I listen to that event
                $http.get('http://demo.com/api/' + num).then(function (response) {
                    $scope.standings = response.data;
                });
            });
        }
    };
});

UPDATE

Here is how I am using it in HTML

<directive-a resource="http://demo.com/api/>
</directive-a>

<directive-b></directive-b>

UPDATE

I am still waiting for its solution.

UPDATE 3

templateA

<ul>
    <li ng-repeat="row in seasons"> 
        <a href="#" ng-click="showDetails(row.season)">{{ row.season }}</a>
    </li>
</ul>

Template B

<h3>Standings</h3>
<table>
    <thead>
        <th ng-repeat="standing in standings" ng-if="state">{{ position  }}</th>
    </thead>
    <tbody>
        <tr ng-repeat="row in standings">
            {{ row.Driver  }}
        </tr>
    </tbody>
</table>
like image 710
Om3ga Avatar asked Aug 25 '16 09:08

Om3ga


1 Answers

Your question boils down to:

  1. How to ensure the communication between DirectiveA and DirectiveB

    As both your directives use the same scope, your solution with event broadcasting works. This would break once you change the scope setting inside DDO to anything else but false.

    That's why I'd advise you $broadcast the event on $rootScope.

  2. How to render DirectiveB's template once data is ready

    A simple ngIf wrapping the directive's template would do the job. We don't need anything fancy for this.

Bellow is a simple working example. Notice how both directives use an isolated scope - this is just to showcase why you need $rootScope.$broadcast. I'm also using $timeout in order to simulate the server's latency.

angular
  .module('myApp', [])
  .directive('directiveA', function() {
    return {
      templateUrl: 'tempA.html',
      controller: function($rootScope, $scope) {
        $scope.sendMessage = function(message) {
          $rootScope.$broadcast('eventName', message);
        };
      },
      scope: {}
    };
  })
  .directive('directiveB', function() {
    return {
      templateUrl: 'tempB.html',
      controller: function($rootScope, $scope, $timeout) {
        $scope.messages = [];

        $rootScope.$on('eventName', function(event, message) {
          $timeout(function() {
            $scope.messages.push(message);
          }, 50);
        });
      },
      scope: {}
    };
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>

<div ng-app="myApp">
  <directive-a></directive-a>
  <directive-b></directive-b>

  <script type="text/ng-template" id="tempA.html">
    <h2>Hello from DirectiveA</h2>
    <label>
      <p>Message to send to DirectiveB</p>
      <input type="text" ng-model="toSend">
    </label>
    <button type="button" ng-click="sendMessage(toSend); toSend = '';">Send</button>
  </script>
  <script type="text/ng-template" id="tempB.html">
    <div ng-if="messages.length > 0">
      <h3>Hello from DirectiveB</h3>
      <ul>
        <li ng-repeat="message in messages track by $index">{{ message }}</li>
      </ul>
    </div>
  </script>
</div>
like image 94
Cosmin Ababei Avatar answered Oct 22 '22 14:10

Cosmin Ababei