0

I know similar questions has been asked in the past, but I hope to get a better understanding to my specific issue.

I have multiple controllers managing the view of a single page. The main reason for this is that the functionality of each controller is vastly different, and I also combined some functionality that used to be on separate views. This is also not an issue that will be resolved by creating a service. I only need to "kick-start" both controllers.

This is my question: I want to implement a single date filter/method on the view, that will call the same method in both controllers to do its functionality, and update the view accordingly.

EDIT: How can I use $scope.on and $scope.emit, or $rootScope to call the function in both controllers?

As per these previously posted questions:

Question 1

Question 2

Here are the two controllers:

angular.module('portalDashboardApp')
  .controller('SocialMentionsAnalysisController', SocialMentionsAnalysisController);

angular.module('portalDashboardApp')
  .controller('SocialMentionsListController', SocialMentionsListController);

This is the method call in my single view:

ng-change="checkDate()

This is the filter method that gets called:

NOTE: Each of the controllers has this method, and I would like to call both these methods via my single method call.

$scope.checkDate = function () {

    var dateValues = DatePickerService.checkDate($scope.dateFrom, $scope.dateTo);
    $scope.dateFrom = dateValues[0];
    $scope.dateTo = dateValues[1];
    $sessionStorage.dateFrom = dateValues[0];
    $sessionStorage.dateTo = dateValues[1];

    pullSocialData();

}; 

I have done research, and this question is perhaps what I need, but I don't know how to implement it.

Community
  • 1
  • 1
onmyway
  • 1,435
  • 3
  • 29
  • 53

2 Answers2

1

I hope i understand correctly the question but you can use directive for this. Instead of use ng-change, you can create your own directive that bin on change of input and check the date here.

For example, your javascript :

app.controller('Ctrl1', function($scope) { })
   .controller('Ctrl2', function($scope) { })
   .directive('checkDate', function(checkDateService) {
      return {
         restrict: 'A',
         scope: true,
         link: function(scope, element, attrs ){
           element.on('change', function() {
             scope.$apply(function() {
               checkDateService.checkDate(scope.from, scope.to);
             })
         });
    }
  }
 }).service('checkDateService', function() {
   return {
     checkDate: function(from, to) {
     console.log(from, to);
   }
 }

});

And the HTML :

<body>
  <div ng-controller="Ctrl1">
    <input type="date" ng-model="from" check-date />
    <input type="date" ng-model="to" check-date />
  </div>
  <div ng-controller="Ctrl2">
    <input type="date" ng-model="from" check-date />
    <input type="date" ng-model="to" check-date />
  </div>
</body>

Here the same sample as plunker :https://plnkr.co/edit/Jqz7Zd4HF0WVBvkJHBbZ?p=preview

To use event in inline js on HTML, I think you can define a methode on $rootScope (at run configuration) that broadcast your event. This event will be triggered by all controller depends on $rootScope.

In Javascript :

app.run(function($rootScope) {
   $rootScope.brodcastDateChanged = function(dateFrom, dateTo) {
      $rootScope.$broadcast('dateChanged', {
         from: dateFrom,
         to: dateTo
      });
    };
})
.controller('Ctrl1', function($scope) { 
    $scope.$on('dateChanged', function(event, args) {
        console.log('event triggered from Ctrl1', args)
    });
 })
 .controller('Ctrl2', function($scope) {  
    $scope.$on('dateChanged', function(event, args) {
         console.log('event triggered from Ctrl2', args)
    });
  })
  .controller('Ctrl3', function($scope) {  
     $scope.$on('dateChanged', function(event, args) {
         console.log('event triggered from Ctrl3', args)
     });
   })

In HTML

<div ng-controller="Ctrl1">
  <input type="date" ng-model="from" ng-change="brodcastDateChanged(from, to)" />
  <input type="date" ng-model="to" ng-change="brodcastDateChanged(from, to)" />
</div>
<div ng-controller="Ctrl2">
  <input type="date" ng-model="from" ng-change="brodcastDateChanged(from, to)" />
  <input type="date" ng-model="to" ng-change="brodcastDateChanged(from, to)" />
</div>
<div ng-controller="Ctrl3">
  <input type="date" ng-model="from" ng-change="brodcastDateChanged(from, to)" />
  <input type="date" ng-model="to" ng-change="brodcastDateChanged(from, to)" />
</div>
Silvinus
  • 1,445
  • 8
  • 16
  • Hi Silvinus. Thank you for the response and great input. I am in fact already making use of a `directive` for the dates. The issue with this is that both the dates (one in each `controller HTML`) doesn't get changed automatically or at the same time. One will still have to change each date for each part of the view controlled by each `controller`. Any thoughts? – onmyway Nov 18 '16 at 06:07
  • If I transpose your comment in my sample, You want change the date from of Ctrl2 when date from of Ctrl1 change and vice versa? – Silvinus Nov 18 '16 at 09:33
  • I am actually trying to call a function in each controller when the data in ctrl 1 changes. I am trying $emit and $scope.$on, but only 2 of the 3 controllers are effected. I think the $emit gets destroyed or something. – onmyway Nov 18 '16 at 09:54
1

The the $on functions with same name will get called with its corresponding single $emit call. I mean, you have multiple $on functions in multiple controllers,

$scope.$on('funtionToTrigger', function(event, args) {
//in first controller
});

$scope.$on('funtionToTrigger', function(event, args) {
//in second controller
});

$scope.$on('funtionToTrigger', function(event, args) {
//in third controller
});

Note: all $on functions' name are same 'funtionToTrigger'. Once you call $scope.$emit('funtionToTrigger', args); then all three $on functions will run in all three controllers.

So here, you have write a $on function in each controller.

function SocialMentionsAnalysisController () {
    $scope.$on('funtionToTrigger', function(event, dateFrom, dateTo) {
    //your code for this controller.
    });
}

function SocialMentionsListController() {
    $scope.$on('funtionToTrigger', function(event, dateFrom, dateTo) {
    //your code for this controller.
    });
}

Then call $emit on onChange.

ng-change="$emit('funtionToTrigger', dateFrom, dateTo)"
Michael Laffargue
  • 10,116
  • 6
  • 42
  • 76
Amir Suhail
  • 1,284
  • 3
  • 12
  • 31
  • Hi Amir, thank you fior the great answer. I have a question; can I add the `$emit` to the function like this: `ng-change="checkDate(); $emit("activate")"` to call this: `$scope.$on("activate", function (event, args) {pullSocialData();});`? – onmyway Nov 18 '16 at 06:48
  • I have set it up as follow: in my date `directive`:`ng-model="dateFrom" ng-change="$emit('dateChanged', dateFrom, dateTo); checkDate()"`, and like this in my `controller`: `$scope.$on("dateChanged", function checkdate(event, dateFrom, dateTo) {var dateValues = DatePickerService.checkDate(dateFrom, dateTo); pullSocialData(); })` This almost works. My `$scope.$on method` gets called in the 1st `controller`, but not in my second `controller`. Any thoughts? – onmyway Nov 18 '16 at 07:29
  • 1
    There is no parent relation between scope's controllers. You need to emit event from $rootScope – Silvinus Nov 18 '16 at 09:39
  • Would I simply inject $rootScope, and change the $scope.on to $rootScope.on? – onmyway Nov 18 '16 at 09:58
  • I changed it to $rootScope, and it works! Thank you :) – onmyway Nov 18 '16 at 10:03