0

I'm taking a pool of random animals, displaying two, then when I click the button of one animal, I want that one to stay and the other to be swapped out for a new one. Right now, I can change the animal that I want to stay in view, but can't figure out how to "reach across" and change the other controller's view.

I've tried setting ng-click="left.findNewAnimal()" on the right side but I get no response on click. I've also looked at using a service or factory, but I'm not sharing data between controllers, I want to change the data of one, from the other. How can this be accomplished?

JavaScript:

angular.module("root", [])
  .controller("leftAnimal", ["$scope",
    function($scope) {
      var self = this;
      var animal

      $scope.findNewAnimal = function() {
        var randNum = Math.floor(Math.random() * animalPool.length);
        animal = animalPool[randNum];
        animalPool.splice(randNum, 1)
        changeAnimal();
      };
      $scope.findNewAnimal();

      function changeAnimal() {
        $scope.name = animal.name;
        $scope.img = animal.img;
      }
    }
  ])
  .controller("rightAnimal", ["$scope",
    function($scope) {
      var self = this;
      var animal

      $scope.findNewAnimal = function() {
        var randNum = Math.floor(Math.random() * animalPool.length);
        animal = animalPool[randNum];
        animalPool.splice(randNum, 1)
        changeAnimal();
      };
      $scope.findNewAnimal();

      function changeAnimal() {
        $scope.name = animal.name;
        $scope.img = animal.img;
      }
    }
  ])
  .factory();



var Animal = function(data) {
  this.name = data.name
  this.img = data.img;
  this.baby = data.baby;
};

var animals = [{
  name: "Baby Quetzal",
  img: "http://i.imgur.com/CtnEDpM.jpg",
  baby: true
}, {
  name: "Baby Otter",
  img: "http://i.imgur.com/1IShHRT.jpg",
  baby: true
}, {
  name: "Baby Octopus",
  img: "http://i.imgur.com/kzarlKW.jpg",
  baby: true
}];

var animalPool = [];

var init = function() {
  animals.forEach(function(animalData) {
    animalPool.push(new Animal(animalData));
  });
}
init();
<!doctype html>
<html ng-app="root">

<head>
  <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="css/main.css">
</head>

<body>
  <div class="row">
    <div class="text-center">
      <h2>Pick an Animal</h2>
    </div>
    <div ng-controller="leftAnimal" class="col-md-6">
      <div class="animalImage">
        <img class="img-center" ng-src="{{img}}">
      </div>
      <div class="animalName">{{name}}</div>
      <div class="animalDescription">{{description}}</div>
      <button type="button" ng-click="findNewAnimal()" class="btn btn-info img-center">{{name}}</button>
    </div>
    <div ng-controller="rightAnimal" class="col-md-6">
      <div class="animalImage">
        <img class="img-center" ng-src="{{img}}">
      </div>
      <div class="animalName">{{name}}</div>
      <div class="animalDescription">{{description}}</div>
      <button type="button" ng-click="leftAnimal.findNewAnimal()" class="btn btn-info img-center">{{name}}</button>
    </div>
  </div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<script src="js/ang.js"></script>

</html>
Community
  • 1
  • 1
Taylor N
  • 500
  • 1
  • 3
  • 15

2 Answers2

0

If you only want simple event exchange between controllers you can use $scope.$emit and $scope.$on :

//right
<button type="button" ng-click="emitEvent()" class="btn btn-info img-center">{{name}}</button>

//right controller
$scope.emitEvent = function(){
  $scope.$emit('changeAnimal');
}

//left controller
$scope.$on('changeAnimal', function(event){
  //do stuff
})

More on $scope events in official docs

shershen
  • 9,875
  • 11
  • 39
  • 60
0

As you stated, you can use Service to communicate to between controllers.

If you want to update other controller update automatically, you want to watch it.

http://plnkr.co/edit/iLnlZDyR1cZUQIiJJJEp

(function () {

angular.module("root", [])
  .controller("leftAnimal", ["$scope", "animalService",
    function ($scope, animalService) {
        var source = false;
        $scope.findNewAnimal = function () {
            var randNum = Math.floor(Math.random() * animalPool.length);
            console.log("Left Click Index: " + randNum);
            animalService.setAnimal(randNum);
            source = true;
        };

        $scope.$watch(function () {
            return animalService.getAnimal();
        }, function (value) {
            if(!source) {
              $scope.animal = animalPool[value];
            }
            source = false;
        });
    }
  ])
  .controller("rightAnimal", ["$scope", "animalService",
    function ($scope, animalService) {
       var source = false;
        $scope.findNewAnimal = function () {
            var randNum = Math.floor(Math.random() * animalPool.length);
            console.log("Right Click Index: " + randNum);
            animalService.setAnimal(randNum);
            source = true;
        };

        $scope.$watch(function () {
            return animalService.getAnimal();
        }, function (value) {
            if(!source) {
              $scope.animal = animalPool[value];
            }
            source = false;
        });
    }
  ])
  .factory("animalService", [function () {
      var index = 0;
      function getAnimal() {
          return index;
      }
      function setAnimal(newIndex) {
          index = newIndex;
      }
      return {
          getAnimal: getAnimal,
          setAnimal: setAnimal,
      }
  }]);

var animalPool = [{
    name: "Baby Quetzal",
    img: "http://i.imgur.com/CtnEDpM.jpg",
    baby: true
}, {
    name: "Baby Otter",
    img: "http://i.imgur.com/1IShHRT.jpg",
    baby: true
}, {
    name: "Baby Octopus",
    img: "http://i.imgur.com/kzarlKW.jpg",
    baby: true
}];
})();
<!DOCTYPE html>
<html ng-app="root">
<head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
    <script src="app.js"></script>
</head>
<body>
    <div class="row">
        <div class="text-center">
            <h2>Pick an Animal</h2>
        </div>
        <div ng-controller="leftAnimal" class="col-md-6">
            <div class="animalImage">
                <img class="img-center" ng-src="{{animal.img}}"/>
            </div>
            <div class="animalName">{{animal.name}}</div>
            <div class="animalDescription">{{animal.description}}</div>
            <button type="button" ng-click="findNewAnimal()"
                    class="btn btn-info img-center">
                Change
            </button>
        </div>
        <div ng-controller="rightAnimal" class="col-md-6">
            <div class="animalImage">
                <img class="img-center" ng-src="{{animal.img}}" />
            </div>
            <div class="animalName">{{animal.name}}</div>
            <div class="animalDescription">{{animal.description}}</div>
            <button type="button" ng-click="findNewAnimal()"
                    class="btn btn-info img-center">
                Change
            </button>
        </div>
    </div>
</body>
</html>
Win
  • 61,100
  • 13
  • 102
  • 181
  • Thank you for taking the time to help me, but this changes both images, and I want to only change one – Taylor N May 24 '16 at 14:21
  • I updated the code. When a button is clicked, other controller's image will be changed. – Win May 24 '16 at 14:31