2

I use controller as approach instead of $scope. I have some problems with method calling from HTML. So, the question is that, how many ways exist in declare and call functions in this approach.

first: (If I want to do s.th. at first)

var vm= this ; 
vm.dataOne=[];

function funcOne() {
        myService.serviceFunc()
            .then(function (response) {
                vm.dataOne= response.data;
            });
    };
function activate() {
        funcOne();
        }
    activate();  

second: (If I want to initialize a variable based on a function returned value )

 vm.dataTwo = function () {
        doSomeThing();
 }  
  • Is there any way, too?
  • How should define a function in controller which will be called from HTML, as

    ng-click = "ctrl.dataTwo()";   
    
Elnaz
  • 2,854
  • 3
  • 29
  • 41
  • 1
    when use `controllerAs` format in your app you should put `vm` instead of $scope before function. if you use function in controller and not use in `HTML` not need to add `vm` before function. – Hadi J May 24 '16 at 09:56
  • Exactly I do this. In first code I didn't use vm since it's as private and will be called locally. But in second code I used vm.dataTwo since I want to access that from HTML as public method. then from HTML I call The ctrl.dataTwo() but I don't know why it doesn't be called. (myController as ctrl ) – Elnaz May 24 '16 at 10:00
  • can you create plunker? – Hadi J May 24 '16 at 10:15
  • 1
    Both your functions are private. To use them, you have to do `vm.funcOne = funcOne;` and `vm.activate = activate;`. BTW, congrats on embracing aliases! You are one step closer to cleaner code. – cst1992 May 24 '16 at 10:45
  • The second function which I told in comment was vm.dataTwo, not activate(). I mean when I use vm.something this is public, otherwise it's private. – Elnaz May 24 '16 at 11:49
  • Good Experiment!! After running more and more and debugging, in last test I saw that finally after 50s the break point activated!!! It seems that the problem is the server big latency. I should test it more to became sure that there is no fault with client-side operations. But I will keep the question body and answer since it could be useful for other as it has good distinguish between functions in controller. Thanks to all. – Elnaz May 24 '16 at 14:19

3 Answers3

5

Functions the way you've defined are private:

function functionOne() {

}; // Just function body, no need of semicolon

These are known as function declarations. Currently, they are only accessible within your controller.

To be able to call them, attach them to the controller so they become controller variables:

vm.functionOne = functionOne;

An advantage of this approach is that you can define functions after actually calling them, as opposed to how you do with $scope or $this. They are recognized via hoisting, and called.

About your initializing a returned value from a function, just call it:

vm.someVariable = someFunction();

Some references:

var functionName = function() {} vs function functionName() {}

Private Members in JavaScript

Angular Function Declarations, Function Expressions, and Readable Code

Angular Style Guide

Community
  • 1
  • 1
cst1992
  • 3,823
  • 1
  • 29
  • 40
  • Ok, as I mentioned I define the methods exactly with this conventions. but the question is that, is there any other way except for theses ways, above? since my functions are not be executed (not called from HTML) – Elnaz May 24 '16 at 11:53
  • 1
    @Elnaz They should most definitely work. Are you sure you're defining them correctly? Post a jsFiddle or Plunker for reference and testing. – cst1992 May 24 '16 at 12:14
0

First way using ng-controller="cntrl as vm" syntax:

<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
   angular.module('MyApp', [])
   .controller('MyCntrl', function($scope) {
       var vm = this;
       vm.name = 'Custom Directive';
   });
</script>
<body>

<div ng-app="MyApp" ng-controller="MyCntrl as vm">
  {{vm.name}}
</div>

</body>
</html>

Second way using controllerAs as one of the attribute of directive:

<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
   angular.module('MyApp', [])
   .directive('customDir', function() {
       return {
           restrict: 'EA',
           template: '<div>{{vm.name}}</div>',
           controller: function(){
               var vm = this;
               vm.name = 'Custom Directive';
           },
           controllerAs: 'vm'
       } 
   });
</script>
<body>

<div ng-app="MyApp">
  <div custom-dir></div>
</div>

</body>
</html>

Way to calling a function with "controller as" syntax which is defined in controller but called in html:

<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
   angular.module('MyApp', [])
   .controller('MyCntrl', function($scope) {
       var vm = this;
       vm.name = 'Custom Directive';

       vm.someFunction = function() {
         vm.name = 'Button is Clicked!!!';
       };
   });
</script>
<body>

<div ng-app="MyApp" ng-controller="MyCntrl as vm">
 {{vm.name}}
 <input type='button' ng-click="vm.someFunction()" value="Click" /> 
</div>

</body>
</html>
Suneet Bansal
  • 2,664
  • 1
  • 14
  • 18
0

Other way, use function as constructor and add functionality to prototype

function Ctrl($window) {
  this.$window = $window;
}

Ctrl.inject = ['$window']

Ctrl.prototype.click = function() {
  this.$window.alert('clicked')
}

angular.module('app', [])
.controller('ctrl', Ctrl)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app='app' ng-controller='ctrl as c'>
  <button ng-click='c.click()'>Click me!</button>  
</div>
Krzysztof Safjanowski
  • 7,292
  • 3
  • 35
  • 47