2

In the below code.

<!DOCTYPE html> <html ng-app="app10" ng-cloak> <head> <title>Custom directives</title> <style> [ng\:cloak], [ng-cloak], .ng-cloak{ display: none; } </style> </head> <body> <div ng-controller="mainCtrl as o"> <div bb-player-list="bbPlayers" array-item="name | uppercase" ng-model="o"> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script> <script type="text/javascript" src="js/exam10.js"></script> </body> </html> 

var app10 = angular.module("app10", []); app10.directive("bbPlayerList", DirectiveFunction); function DirectiveFunction(){ return function(scope, element, attrs){ var data = ""; if(attrs["ngModel"] === "") data = scope[attrs["bbPlayerList"]]; else data = scope[attrs["ngModel"]][attrs["bbPlayerList"]]; } } app10.controller("mainCtrl", MainController); function MainController(){ this.bbPlayers = [ {name: "Barry Bonds", avg: 0.298, hr: 762, obp: 0.444}, {name: "Hank Aaron", avg: 0.305, hr: 755, obp: 0.374}, {name: "Babe Ruth", avg: 0.342, hr: 714, obp: 0.474}, {name: "Ted Williams", avg: 0.344, hr: 521, obp: 0.482} ]; } 

In DirectiveFunction, there is a code smell in retrieving the data using ngModel,

 var data = ""; if(attrs["ngModel"] === "") data = scope[attrs["bbPlayerList"]]; else data = scope[attrs["ngModel"]][attrs["bbPlayerList"]]; 

Reason to add this code smell is,

if controller is instantiated like mainCtrl as o then ngModel would be "o" otherwise ngModel will be "". This attribute ngModel will decide, how to access bbPlayers in DirectiveFunction?

Can I avoid this code smell in DirectiveFunction?

How does DirectiveFunction get immune to, the way mainCtrl is instantiated?

1 Answer 1

1

You should consider require-ing the ngModelcontroller (and the MainController, if needed) inside your directive definition instead of inspecting the attrs inside of the link function:

function DirectiveFunction(){ return { require: [ '^ngController', '?ngModel' ], link: (scope, element, attrs, controllers) => { const [ MainController, ngModel ] = controllers; data = main.bbPlayers; } }; } 

It appears that you're trying to share data between controllers, however, which is best done through a shared, named service. Consider instead:

angular.module('app10') .factory('Players', function(){ // injectable, if you need it... return [ {name: "Barry Bonds", avg: 0.298, hr: 762, obp: 0.444}, {name: "Hank Aaron", avg: 0.305, hr: 755, obp: 0.374}, {name: "Babe Ruth", avg: 0.342, hr: 714, obp: 0.474}, {name: "Ted Williams", avg: 0.344, hr: 521, obp: 0.482} ]; }) .directive('bbPlayerList', function(){ // also injectable... return { controller: function(Players){ // injectable again... // Do stuff with `Players` if you need to... } } }); 

If you need to fetch the data from a server and cache the results, you can put that logic in the setup of Players or expose a method that will do the same:

angular.module('app10') .factory('Players', function(){ // injectable again... return { all: () => [ {name: "Barry Bonds", avg: 0.298, hr: 762, obp: 0.444}, {name: "Hank Aaron", avg: 0.305, hr: 755, obp: 0.374}, {name: "Babe Ruth", avg: 0.342, hr: 714, obp: 0.474}, {name: "Ted Williams", avg: 0.344, hr: 521, obp: 0.482} ] }; }); 

Then call Players.all() inside any constructor to get all the players. You can easily replace the dummy data with a call to an endpoint with $http or $resource or Restangular.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.