StrugglingCoder
StrugglingCoder

Reputation: 5021

Replace $scope with this by turning on ControllerAs

I thought to replace $scope with this keyword in my sample Angular code base and in turn to switch to using ControllerAs syntax.

But in turn this does not seem to work now.

I have a list of countries in my controller and in my custom directive whenever a country name is clicked , I show the map of the respective country.

<body ng-controller="appCtrl as vm">

<nav class="navbar navbar-default">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">Welcome to the world of directives!</a>
        </div>
        <ul class="nav navbar-nav">
            <li ng-repeat="countryTab in vm.countries" ng-click="vm.itemClicked(countryTab)" style="cursor:pointer">
                <a>{{countryTab.label}}</a>
            </li>
            <br>
        </ul>
    </div>
</nav>
<data-country-tab-bar country="vm.selectedCountry"  ng-if="vm.selectedCountry">
    <strong><i>Check out our cool new directive!</i></strong>
</data-country-tab-bar>
<script>
    var app = angular.module('app',[]);
    app.controller('appCtrl',function($scope,$http){
        this.countries = [{
          id: 1,
          label: 'Italy',
          coords: '41.29246,12.5736108'
        }, {
          id: 2,
          label: 'Japan',
          coords: '37.4900318,136.4664008'
        }, {
          id: 3,
          label: 'USA',
          coords: '37.6,-95.665'
        }, {
          id: 4,
          label: 'India',
          coords: '20.5937,78.9629'
        }];

        this.itemClicked = function(value){
            this.selectedCountry = value;
        }


    });

And in my directive , I just bind the country object that is the part of my DDO's isolated scope , to that of the controller's.

        app.directive('countryTabBar',function(){
            return {
                restrict: 'E',
                transclude:true,
                replace:true,
                $scope:{
                    country: '='
                },
                template: '<div>'+
                '   <div><strong>{{country.label }}</strong> : {{ country.coords}}</div>'+
                '   <br/>'+
                '   <img ng-src="https://maps.googleapis.com/maps/api/staticmap?center={{country.coords}}&zoom=4&size=800x200"> '+      
                '   <br/><br/>'+
                '   <div ng-transclude></div>'+
                '</div>',
            }
        });
    </script>
</body>

But , I can see the transcluded string Check out our cool new directive! but I can't see the map.

There is no error as such in console.

Please help.

Upvotes: 0

Views: 124

Answers (1)

Ovidiu Dolha
Ovidiu Dolha

Reputation: 5413

I think the problem is related to:

this.itemClicked = function(value){
  this.selectedCountry = value;
}

this.selectedCountry in a function declared so in JavaScript will refer to the current function, not the controller (parent function) as you expect.

Solution (ES5):

var vm = this;
this.itemClicked = function(value){
  vm.selectedCountry = value;
}

Solution (ES6):

this.itemClicked = value => this.selectedCountry = value;

Additionally, the directive scope syntax seems to be incorrect:

$scope:{
  country: '='
},

Should be:

scope:{
  country: '='
},

Hope this helps.

Upvotes: 2

Related Questions