Showing posts with label AngularJS. Show all posts
Showing posts with label AngularJS. Show all posts

Tuesday, 17 September 2019

Converting AngularJS $q to JavaScript Promise

Since I had to upgrade my app from AngularJS to Angular, I would also need to change my promise returned codes. I needed to change all of my codes that were using $q AngularJS service to the new JavaScript Promise.
These codes:
getItems = function () {
  var deferred = $q.defer();

  try {
   . . .
   deferred.resolve(itemsToBeReturned);
  }
  catch(error) {
   . . .
   deferred.reject(error);
  }
  
  return deferred.promise;
};
are converted into:
getItems() {
 return new Promise((resolve, reject) => {
   try {
    . . .
    resolve(itemsToBeReturned);
   }
   catch(error) {
    . . .
    reject(error);
   }
 });
};
The consuming function can remain the same:
this.getItems()
 .then((items) => {
  // success
  . . .
 })
 .catch(error => {
  // error
  . . .
 });

The new JavaScript Promise also allowed the promises returned to be chained:
getItems() {
 return new Promise((resolve, reject) => {
  this.doSomething()
   .then((rs) => {
    . . .
    return Promise.resolve(123); 
   })
   .then((rs) => {
    . . .
    return 456;   // this returns a promise as well
   })
   .then((rs) => { 
    . . .
    resolve(result); 
   })
   .catch(error => reject(error));
 });
};


Reference:
Promise - TypeScript Deep Dive

Monday, 19 September 2016

Directive to Parse and Format Number from and to Currency

This post will show an example of an AngularJS directive that will automatically format a plain number inserted into an input field into a currency format. As the number is typed into the input field, the value will be formatted into its local currency representation. The directive also converts a number value from model to its currency format in the view.
$formatters, $parsers and $filter are used as part of the codes.
myApp.directive('formatCurrency', ['$filter', '$locale', function ($filter, $locale) {
    return {
        require: '?ngModel',
        link: function (scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            // $formatters is used to process value from code to view
            ctrl.$formatters.unshift(function (modelValue) {
                var formattedValue;
                if (modelValue) {
                    formattedValue = $filter('currency', null, 2)(modelValue);  // use $filter to do some formatting
                } else {
                    formattedValue = '';
                }
                return formattedValue;
            });

            // $parsers is used to process value from view to code
            ctrl.$parsers.unshift(function (viewValue) {
                var plainNumber;
                var formattedValue;
                
                var decimalSeparatorIndex = viewValue.lastIndexOf($locale.NUMBER_FORMATS.DECIMAL_SEP);  // $locale.NUMBER_FORMATS.DECIMAL_SEP variable is the decimal separator for the current culture
                if (decimalSeparatorIndex > 0) {
                    // if input has decimal part
                    var wholeNumberPart = viewValue.substring(0, decimalSeparatorIndex);
                    var decimalPart = viewValue.substr(decimalSeparatorIndex + 1, 2);
                    plainNumber = parseFloat(wholeNumberPart.replace(/[^\d]/g, '') + '.' + decimalPart).toFixed(2); // remove any non number characters and round to two decimal places

                    formattedValue = $filter('currency', null, 2)(plainNumber);
                    formattedValue = formattedValue.substring(0, formattedValue.lastIndexOf($locale.NUMBER_FORMATS.DECIMAL_SEP) + 1);
                    formattedValue = formattedValue + decimalPart;
                } else {
                    // input does not have decimal part
                    plainNumber = parseFloat(viewValue.replace(/[^\d]/g, ''));
                    formattedValue = $filter('currency', null, 0)(plainNumber);     // the 0 argument for no decimal does not work (issue with Angular)

                    if (formattedValue) {
                        // remove the decimal part
                        formattedValue = formattedValue.substring(0, formattedValue.lastIndexOf($locale.NUMBER_FORMATS.DECIMAL_SEP));
                    } else {
                        formattedValue = viewValue;
                    }
                }

                elem.val(formattedValue);
                return plainNumber;
            });
        }
    };
}]);

To use it on an input field:
<input type="text" ng-model="vm.myVariable" format-currency/>

For a working example, please see this on Plunker.

Friday, 2 September 2016

Passing Controller Function to Directive

Below is an example of how to call a controller function from inside an AngularJS directive:
myApp.directive('myDirective', function () {
    return {
        scope: { controllerFunction: '&callbackFunction' },
        link: function (scope, element, attrs) {
            scope.controllerFunction({ arg: '123' });
        },
    }
});
And the markup:
<div ng-controller="MyCtrl as vm">
      <span my-directive callback-function="vm.theControllerFunction(arg)" ></span>
</div>

We can also call the controller function whenever a value in the directive changes. An example of such directive:
myApp.directive('observeValueChange', function () {
    return {
        scope: { controllerFunction: '&callbackFunction' },
        link: function (scope, element, attrs, ngModel) {
            attrs.$observe('theValue', function (newValue) {
                scope.controllerFunction({ arg: newValue });
            })
        },
    }
});
The markup:
<input type="text" ng-model="vm.myVariable" />
      <span observe-value-change the-value="{{vm.myVariable}}" callback-function="vm.theControllerFunction(arg)" ></span>

See the working example in Plunker.

Tuesday, 27 October 2015

A Form Validation Example in AngularJS - Show Error Style After Submitted

Below is a basic example of a form validation in AngularJS that shows error style after the form is submitted.

To do this, we need to use novalidate attribute on the form to avoid browser validating the form but is passed to JavaScript to perform manual validation. In addition, we can utilise ng-submitted class that is added to the form by AngularJS after it is submitted.

The view:
<body ng-app="validationExample">
    <div ng-controller="MyCtrl as vm">
      <form name="myForm" novalidate ng-submit="vm.submitted(myForm, vm.input)">
        <input type="text" name="name" ng-model="vm.input.name" placeholder="please enter text" required/>
        <span ng-show="myForm.name.$error.required == true">*</span>
        <input type='text' name="value" ng-model='vm.input.value' placeholder="a number greater than 0" required ng-pattern='/^([1-9][0-9]*(\.[0-9]+)?|0+\.[0-9]*[1-9][0-9]*)$/'>
        <span ng-show="myForm.value.$error.required == true">*</span>
        <button>submit</button>
      </form>
    </div>
</body>

The script:
var myApp = angular.module('validationExample', [])

myApp.controller('MyCtrl', [function () {
    var vm = this;
    vm.submitted = function(form, input) {
      if(form.$valid) {
        alert('submitted');
      }
    }
} ]);

The stylesheet:
.ng-submitted input.ng-invalid {
  border-color:red;
}

See the example in Plunker.

To read more about form validation, please see my previous post.

Thursday, 1 October 2015

Table with Dynamic Rows Manipulation Example in AngularJS

Below is a code example of building a table with the ability to add, edit and remove rows dynamically with AngularJS. It also makes the corresponding input in focus.

The view:
<html>
  <head>
    <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script src="https://code.angularjs.org/1.2.16/angular.js"></script>
    <script src="script.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="MyCtrl as vm">
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Value</th>
          </tr>
        </thead>
        <tbody>
          <tr ng-repeat="row in vm.rows">
            <td>
              <input type="text" ng-model="row.name" ng-readonly="row.readonly" ng-disabled="row.readonly" on-focus="!row.readonly" />
            </td>
            <td>
              <input type="text" ng-model="row.value" ng-readonly="row.readonly" ng-disabled="row.readonly" />
            </td>
            <td>
              <button ng-click="vm.editRow($index)">{{row.readonly ? "Edit" : "Save" }}</button>
              <button ng-click="vm.removeRow($index)">Remove</button>
            </td>
          </tr>
        </tbody>
      </table>
      <br />
      <input type="button" value="Add New" ng-click="vm.addNewRow('','')" />
    </div>
  </body>
</html>

The script:
angular.module('myApp', [])
.controller('MyCtrl', function () {
    var vm = this;
    vm.rows = [{"name": "aaa", "value" : 50, "readonly": true}, {"name": "bbb", "value" : 70, "readonly": true}];
    
    vm.addNewRow = function(name, value) {
      vm.rows[vm.rows.length - 1].readonly= true;
      vm.rows.push({"name":"", "value":"", "readonly": false})
    }
    
    vm.removeRow = function(index) {
      vm.rows.splice(index, 1);
    }
    
    vm.editRow = function(index) {
      vm.rows[index].readonly = !vm.rows[index].readonly;
    }
})
.directive('onFocus', function($timeout) {
    return function(scope, element, attrs) {
        scope.$watch(attrs.onFocus, function (newValue) {
            if (newValue) {
                $timeout(function () {
                    element.focus();
                }, 0, false);
            }
        }); 
      };    
});

See the example in action on Plunker.

Monday, 18 May 2015

Using When, All, Then and Reject functions of $q Service

We will see how to use when, all, then and reject functions of the AngularJS $q service. To learn the basic usage of $q, please see my previous post.

$q.when
$q.when() can be used to wrap an object or function if we are not sure whether it returns a promise or not. If we wrap a value object or a value returned function, the value will be passed as a result argument to the next function. When we wrap a function, the when() method will ensure that the function is executed first before going to the next one.

Below are some code examples:
$q.when('aaa').then(function(result) {
    alert(result);
})

var vm = this;
vm.chars = '';

$q.when(_test()).then(function(){
 vm.chars = vm.chars + 'END'
})

_test = function() {
 for (i = 0; i <= 10000; i++) {
   vm.chars = vm.chars + '.'
 }
}


$q.all
$q.all() is used to combine promise returned functions and only continue to progress further after all of the functions complete successfully. If one of the functions fails, immediately as soon as $q.all() gets a rejected promise from one of the functions, it will end the execution and pass forward to an error callback if there is any.
vm.numbers = '';    
_promiseFunction = function(x) {
 var deferred = $q.defer();

 if (x > 0) {
   deferred.resolve(x * 100);
 } else {
   deferred.reject(x + " is smaller than 0")
 }

 return deferred.promise;
}
 
var first = _promiseFunction(1);
var second = _promiseFunction(5);
var third = _promiseFunction(10);
var four = _promiseFunction(-1);
var five = _promiseFunction(-10)

$q.all([first, second, third /*, four, five*/]).
then(function(results){
  console.log(results.length);
  for(i=0; i < results.length; i++) {
    vm.numbers = vm.numbers + ' ' + results[i];
  }
 },
 function(errors){
  // if there is any error in the sequence, the success callback will not be called
  console.log(errors);
 })


$q.then
$q.then() is useful for executing asynchronous functions (or blocks of codes) sequentially in a chain. If the function inside a then() does not return a promise, it will be wrapped as a resolved promise. Otherwise the resolved or rejected promise will be passed forward.

_promiseFunction(5).then(
 function() { alert('aaa')}
).then(
 function() { alert('bbb');}
).then(
 function() {alert('ccc');}
);

_promiseFunction(5).then(
 function() { return $q.reject('failed')}
).then(
 function(){ alert('result success')},
 function(){ alert('result fail')}
)

Note also that if we return a non-promise value in the error callback inside then(), this will be treated as a resolved promise. So we need to be careful when handling error if our intention is to pass the error forward to the next function.
$q.reject().then(
 // success
 function() {},
 // error
 function(error) {
   return 'i got the error'
 }
).then(
 //success
 function() {
   alert('success');
 },
 // error
 function() {
   alert('error')
 }
)

$q.reject
Last thing, we have $q.reject() that is useful as a quick way to create then send a rejected promise (with a value optionally) to the next function in a chain. For example, in a chain of multiple then(). We can see this in the last two examples.

See the examples in Plunker.

Wednesday, 29 April 2015

AngularJS Custom Validator Example - Comparing Two Dates

Below is an example of AngularJS custom validator to compare an end date with a start date to make sure that the end date is equal or bigger than the start date. To see basic usage of AngularJS validation, please see my previous post.

HTML codes:
<!DOCTYPE html>
<html>

  <head>
    <script src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
    <script src="https://code.angularjs.org/1.3.15/angular-messages.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-app="validationExample">
    <div ng-controller="MyCtrl as vm">
      <form name="myForm" novalidate="" ng-submit="vm.submitted(myForm, vm.input)">
        <span class="input-label">Start Date</span> 
        <input type="date" name="startDate" ng-model="vm.input.startDate" required />
        <span ng-messages="myForm.startDate.$error" ng-messages-include="errors-template.html"></span>
        <br />       
        <span class="input-label">End Date</span> 
        
        <input type="date" name="endDate" ng-model="vm.input.endDate" start-date="{{vm.input.startDate.yyyymmdd()}}" compare-with-start-date />
        <span ng-messages="myForm.endDate.$error" ng-messages-include="errors-template.html"></span>
        <br />             
        <button>submit</button>
      </form>
    </div>
    
    <!-- error messages template -->
    <script id="errors-template.html" type="text/ng-template">
        <span ng-message="required">* required!</span>
        <span class="form-error" ng-message="checkEndDate">* end date cannot be earlier than start date</span>
    </script>
  </body>

</html>

JavaScript codes:
var myApp = angular.module('validationExample', ['ngMessages'])

myApp.controller('MyCtrl', [function () {
    var vm = this;
    vm.submitted = function(form, input) {
      if(form.$valid) {
        alert('submitted');
      }
    }
} ]);

myApp.directive("compareWithStartDate", function () {
    return {
        restrict: "A",
        require: "?ngModel",
        link: function (scope, element, attributes, ngModel) {
            validateEndDate = function (endDate, startDate) {
                if (endDate && startDate) {
                    startDate = new Date(startDate);
                    startDate.setHours(0, 0, 0, 0);
                    endDate = new Date(endDate);
                    endDate.setHours(0, 0, 0, 0);
                    return endDate >= startDate;
                }
                else {
                    return true;
                }
            }

            // use $validators.validation_name to do the validation
            ngModel.$validators.checkEndDate = function (modelValue) {
                var startdate = Date.parse(attributes.startDate);
                var enddate = modelValue;
                return validateEndDate(enddate, startdate);
            };
            
            // use $observe if we need to keep an eye for changes on a passed value
            attributes.$observe('startDate', function (value) {
                var startdate = Date.parse(value);
                var enddate = Date.parse(ngModel.$viewValue);
                
                // use $setValidity method to determine the validation result 
                // the first parameter is the validation name, this name is the same in ng-message template as well
                // the second parameter sets the validity (true or false), we can pass a function returning a boolean
                ngModel.$setValidity("checkEndDate", validateEndDate(enddate, startdate));
            });
        }
    };
});


// function to parse date time object into yyyy-mm-dd format string
Date.prototype.yyyymmdd = function () {
    var yyyy = this.getFullYear().toString();
    var mm = (this.getMonth() + 1).toString(); // getMonth() is zero-based         
    var dd = this.getDate().toString();

    return yyyy + '-' + (mm[1] ? mm : "0" + mm[0]) + '-' + (dd[1] ? dd : "0" + dd[0]);
};

See the example in Plunker.

Thursday, 16 April 2015

Form Validation in Ionic or AngularJS

On this post we will see how to do form validation in AngularJS or Ionic framework. At the moment, Ionic framework does not have its own validation features and relies on the underlying framework.

Basic Usage with Built-In Validators
To begin, first we need to make sure that we have a reference to angular.js file. Then we need to do the following steps:
- give a name to our form
- put novalidate="" attribute on the form
So we should have something like this on our form:
<form name="myForm" novalidate="" ng-submit="" >
 . . .
</form>
- add a unique name to each input field
- add validation attributes that we need on the input fields. AngularJS provides some validation directives such as these; required, pattern, minlength, maxlength, min and max. It also has basic built-in validators for these input types; text, number, url, email and date.
An example on an input field:
<input type="text" name="name" ng-model="vm.input.name" required />
- add an error message to be displayed for each validator checking the corresponding property name on input field's $error object in conditional statement like ng-if or ng-show. Properties under $error object with the same names as the validators' names exist for us to use. The properties are on this format; formName.fieldName.$error.builtInValidatorName. For example:
<span ng-show="myForm.name.$error.required == true">* required</span>
- on a method that is called in ng-submit, check whether the form is valid using formName.$valid before doing any action

Below is a complete example:
<!-- HTML page -->
<body ng-app="validationExample">
    <div ng-controller="MyCtrl as vm">
      <form name="myForm" novalidate="" ng-submit="vm.submitted(myForm, vm.input)">
        <div>
          <input type="text" name="name" ng-model="vm.input.name" required>
          <span ng-show="myForm.name.$error.required == true">test: * required</span>
        </div>
        <button>submit</button>
      </form>
    </div>
</body>

// JavaScript codes
var myApp = angular.module('validationExample', [])

myApp.controller('MyCtrl', [function () {
    var vm = this;
    vm.submitted = function(form, input) {
      if(form.$valid) {
        // post the form
        . . .
      }
    }
} ]);
See these codes on Plunker.


Creating Custom Validator
If we would like to create a custom validator, we would need to do these in addition of the above steps:
- create a directive
- on the directive's link function, use the new AngularJS $validators object on ngModel controller to do the validation. We need to create a function property on ngModel.$validators. By doing so, we register the function as a new validation rule. Each time the model changes, the validation rule is invoked. For example:
link: function(scope, element, attributes, ngModel) {
 ngModel.$validators.wrongInitial = function(modelValue) {
   . . .
 };
}
A corresponding property on input field's $error object is also created that can be used for checking validity.
- similar like in using built-in validator, we need to add an error message to be displayed by checking the newly created corresponding property on the input field's $error object:
<span ng-show="myForm.name.$error.wrongInitial == true">* must start with letter r</span>

Additional codes to be added from the first example:
<!-- HTML page -->
<input type="text" name="name" ng-model="vm.input.name" start-with-r />
<span ng-show="myForm.name.$error.wrongInitial == true">* must start with letter r</span>

// JavaScript codes
myApp.directive("startWithR", function() {
    return {
      restrict: "A",
      require: "?ngModel",
      link: function(scope, element, attributes, ngModel) {
        ngModel.$validators.wrongInitial = function(modelValue) {
          if (modelValue) {
            return modelValue.charAt(0).toUpperCase() == 'R';
          }
          else {
            return true;
          }
        };
      }
    };
});
See a complete example on Plunker.


Using ngMessages to Display Error Messages
In the recent version of AngularJS, started with version 1.3, there is a new feature that we could use to display messages including form error messages. To use this, we need to:
- include a reference to angular-messages.js file in our page
- inject ngMessages module to our AngularJS app
var myApp = angular.module('validationExample', ['ngMessages'])
- if there are only a few fields to be validated, we could specify each error message for each field like this:
<!-- use ng-messages with each field's $error object in this format; formName.fieldName.$error -->
<div ng-messages="myForm.name.$error" >  
        <!-- specify an error message for each validator -->
 <span ng-message="required">Name is required!</span>
 <span ng-message="wrongInitial">Name must start with letter r</span>
</div>
- however if we know that we are going to repeat this multiple times, we could use a template instead:
<!-- create a template by using script tag with type="text/ng-template" and give an Id -->
<script id="errors-template.html" type="text/ng-template" >  
        <!-- specify an error message for each validator -->
 <span ng-message="required">* required!</span>
 <span ng-message="wrongInitial">* must start with letter r!</span>
</script>
Then use the template to display error message(s) on each field:
<!-- use ng-messages with each field's $error object and ng-messages-include referring to the template Id -->
<span ng-messages="myForm.name.$error" ng-messages-include="errors-template.html" />
See the complete example on Plunker.


References:
Working with Validators and Messages in AngularJS
Validation in Ionic Framework Apps with ngMessages

Monday, 5 January 2015

Implementing Asynchronous Tasks with $q in AngularJS

AngularJS has provided $q service that can be used to implement asynchronous tasks. It uses deferred objects and the promises they return to accomplish asynchronous runs.

A basic example of using $q:
function myAsyncFunc() {
  // create a deferred object
  var deferredObject = $q.defer();

  . . .

  // if for a reason, we want to cancel this task
  if (errorOccured) {
        deferredObject.reject('an error has occured');
        return deferredObject.promise;
  }

  // after the job is completed, call resolve()
  deferredObject.resolve();

  . . .

  // return the promise
  return deferredObject.promise;
}

// then on the caller
myAsyncFunc().then(
  // success (when resolve() was called)
  function() {
    alert('success')
  },
  // error (when reject() was called)
  function(reason) {
    alert('failed: ' + reason)
  }
)

We can also return an object when the task is completed. To do this, just pass the object as an argument to the resolve() function instead of nothing. Below is an example:
function myAsyncFunc() {
  var myObject = . . .
  deferredObject.resolve(myObject);
}

// then on the caller, we can use the passed object
myAsyncFunc().then(
  // success
  function(passedObj) {
    . . .
  }
);

When resolving a deferred object, we can use deep nesting functions if required. As long as the deferred object variable is accessible, this should not be an issue:
var deferredObject; // need to make sure that this deferred object variable will be accessible from inside nesting function

function myAsyncFunc() {
  // create a deferred object
  deferredObject = $q.defer();

  . . .

  nestedOne();

  // return the promise
  return deferredObject.promise;
}

function nestedOne() {
  nestedTwo();
}

function nestedTwo() {
  deferredObject.resolve();
}

Wednesday, 10 December 2014

Some Guidelines to Design Clean Controller and Service

An AngularJS controller should not be burdened with other tasks other than mediating interaction between view and data that comes from one or more services. The data model, data management and application business logic should be written in services. I also like to use controllerAs with 'this' approach. Also include as few services as possible in the controller. If a controller has too many services then this should be questioned. Instead we should try to use services that aggregate other required services inside.

Below is an example of a controller:
myApp.controller('MedicineCtrl', ['medicineService',
 function (medicineService) {
     var vm = this;
     vm.medicineNames = medicineService.medicineNames;
     vm.addMedicine = function (input) {
         medicineService.addMedicine(input);
     };
     vm.updateMedicine = function (input) {
         medicineService.updateMedicine(input);
     };
     vm.deleteMedicine = function (id) {
         medicineService.deleteMedicine(id);
     };
}]);
Of course, this is a simplified example however this should give us a picture of what a controller should be designed like.

For the service, it's recommended to have 'private' variables and functions needed and only expose publicly the ones that are necessary as service object's properties. Also whenever possible, try to design the functions to run asynchronously using AngularJS promise (will show an example in the next post). Below is an example of a service:
myApp.factory('medicineService', ['otherService1', 'otherService2', 
  function (otherService1, otherService2) {
    // 'private' variables and functions
    var _medicines = [];
    var _privateVarOne;
    var _privateVarTwo;
    
    _addMedicine = function (input) {
       . . .
       // some business logic
       . . .
    };

    _updateMedicine = function (input) {
       . . .
       // some business logic
       . . .
    };

    _deleteMedicine = function (id) {
       . . .
       // some business logic
       . . .
    };

    _anotherPrivateFunction = function () {
       . . .
       // some business logic
       . . .
    };

    // only expose publicly the required members
    return {
        medicineNames: _medicineNames,
        addMedicine: _addMedicine,
        updateMedicine: _updateMedicine,
        deleteMedicine : _deleteMedicine 
    }
}]);

Wednesday, 3 December 2014

AngularJS ControllerAs and Scope

If we set up a view and controller with controllerAs like below:
// in routing configuration
. . .
.when('/pageOne', {
        templateUrl: 'partials/page-one.html',
        controller: 'CtrlOne',
        controllerAs: 'vm'
})
. . .
// the controller
userApp.controller('CtrlOne', [function () {
    var vm = this;
    vm.nameOne = "test";
    vm.getName = function () {
        return 'aaa';
    };

    this.nameTwo = "blah";
    var nameThree = "ggg"; // not visible from outside
}]);
then we will have these scopes when the page loads:



The first scope is the root scope and the one underneath it is the scope created for the controller. As the picture shows, the variables are created as properties of 'vm' object. If we had used the traditional approach by defining variables on $scope such as $scope.myVariable = ... then these variables would be created on the first level on controller scope (not wrapped inside an object). We can also see when we use controllerAs, other variable that is defined directly not through 'this' object will not be visible from outside.


Adding a Child Controller

Let us add a child controller inside our controller. The child controller:
userApp.controller('ChildCtrl', [function () {
    var vm = this;
    vm.dataOne = 'sss';
    vm.getData = function () {
        return 'bbb';
    }
}]);
And change our view to be like this:
<div>
    Page One
    <div>
        <div>{{parentVm.nameOne}}</div>
        <div ng-controller="ChildCtrl as childVm">
            {{childVm.dataOne}}
            {{parentVm.nameOne}}
        </div>
    </div>
</div>

Now we can see that a new scope is created for the child controller:




Accessing Parent Controller's Variables

On the view, we can simply use '{{parentVm.variableName}}' to refer to a parent controller's variable.

In the child controller script function, accessing parent's variables which controller uses controllerAs is not as easy as if the parent controller had used $scope to register its properties. One way to do this is by using $scope help in the child controller. We need to inject $scope to the controller then refer to the parent controller's instance name to be able to access its variables/properties. Below is an example:
$scope.parentVm.nameOne = 'modify parent var';
//$scope.$parent.parentVm.nameOne = 'modify parent var';    // or could use $parent
The code on the first line is utilising JavaScript prototypal inheritance where it will try to find the property 'parentVm.nameOne' on the current scope then if it is not found, it will try to find on the parent scope and so on until it reaches the root scope. This AngularJS documentation 'Understanding Scope' explains it in more details.
The second code is finding the property on the parent scope. We could append many $parent if required.

If we had tried to do these below inside child controller:
vm.nameOne = 'modified';
$scope.nameOne = 'hhh';
new variables would be created on the current scope. One is on the scope's root level and the other one is inside an object. The picture below shows this:




Creating Local Variables that Hold References

If we want to create a local variable that holds reference to a variable in parent controller then we need to create that variable as an object in parent controller. This is explained as well in the referred AngularJS documentation above. For example:
// create an object variable in parent controller
vm.objVar = { name: 'aaa' };
then in our child controller:
// create the local variable in child controller
vm.childRefVar = $scope.$parent.parentVm.objVar;

// try to do some update
$scope.$parent.parentVm.objVar.name = 'jjj'; // when we update the variable in parent controller, this will reflect in both parent and local variables
vm.childRefVar.name = 'bbb'; // when we modify the local variable, this will reflect in parent variable as well


Best Practices

As we have seen above, accessing variables in parent controller is not straight forward. If you are going to have nested controllers in your view, it is recommended to use a service to share data between the controllers rather than using variables/properties in your controller.

If you do not want to use a service then I think it is better to register the variables or functions that are going to be shared on $scope rather than on 'this' object unless you are going to decide/know the controller's alias object name in advance to be used from codes inside child controller.

Thursday, 13 November 2014

Cordova Plugin is not Available when Application Starts

If you use a plugin and execute its method when your application starts and have this error:
TypeError: Cannot read property '[your_plugin_name]' of undefined at Object.[plugin_method]
then it is likely that the plugin has not been initialised fully when the method is called.

To solve this issue, wait until deviceready event is fired before calling the plugin's method.

With AngularJS, I like to wait until deviceready event is fired before loading the whole application. To do this, make sure that ng-app declaration is removed from the HTML, then bootstrap the app when deviceready event has fired. document.addEventListener is used to determine whether the event has been fired.
document.addEventListener("deviceready", function() {
    angular.bootstrap(document, ["myApp"]);
}, false);
If you want to apply this to a particular element instead of the whole HTML document (or body), you could use:
var theElement = document.findByID(...) // or document.querySelector(...);
angular.bootstrap(theElement, ["myApp"]);

Then you can call the rest scripts:
var myApp= angular.module('myApp', [. . .]);

myApp.config(
  . . .
);

Friday, 10 October 2014

Basic Navigation in Ionic

On this post we will see how to do basic navigation in Ionic Framework.

1. First we need to configure the routes in AngularJS:
app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
  .state('home', {
    url: '/',
    templateUrl: 'home.html'
  })
  .state('pageOne', {
    url: '/page1',
    templateUrl: 'one.html'
  })
  .state('anotherPage', {
    url: '/whatever',
    templateUrl: 'myhtml.html'
  });
  
   $urlRouterProvider.otherwise("/");
});
In the example we use UI Router to manage our routes. Each route has a state name, a defined url and an actual path for the view content. In the end, we also define the default url to be called when a url targeted does not match any in configurations.


2. Then on our main page, we just need to use
<ion-nav-view></ion-nav-view>
It will be useful to add a navigation bar with back button and also to have an animation effect like this:
<ion-nav-bar class="bar-positive">
        <ion-nav-back-button class="button-icon ion-arrow-left-c">
        </ion-nav-back-button>
    </ion-nav-bar>

    <ion-nav-view animation="slide-left-right"></ion-nav-view>
When we use Ionic navigation back button, the scripts behind it automatically do the job in storing page histories and pulling out the previous page as well as redirecting to the page when clicking the element.


3. Finally create each partial view using
<ion-view>
  <ion-content>
    . . .
  </ion-content>
</ion-view>


For a complete working example, please see here in Plunker.

Thursday, 26 June 2014

Watching Attribute Value with $observe

Below is an example of how to watch for an attribute's value and do something every time it has changed. To do this we would use $observe function.

<!-- origin markup in the view -->
enter a colour: <input class="observe-test" data-ng-model="inputValue" title="{{inputValue}}"/> 
<br />
value typed: <span></span>

// directive codes
myApp.directive('observeTest', function () {
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            attrs.$observe('title', function (newValue) {
              attrs.$set('style', 'color:' + newValue);
              element.parent().find('span').text(newValue);
            })
        }
    }
});

See the example in Plunker

Monday, 23 June 2014

More Advanced AngularJS Directive

Isolate Scope
scope option is useful for creating directive's internal variables or functions from outer values or functions.
<!-- origin markup in the view -->
<scopetest a-value="controllerData" the-value="{{controllerData}}" show-value="showPopup()"></scopetest>

// these codes are inside the controller
$scope.controllerData = 'Oii';
$scope.showPopup = function () {
    alert($scope.controllerData);
}

// directive codes
myApp.directive('scopetest', function () {  // would work as well if I had used myApp.directive('showValue' . . . restrict: 'A'
    return {
        restrict: 'E',
        template: "<p>controllerData: {{controllerData}}</p> <p>data: {{data}}</p> <p>theData: {{theData}}</p> <p>sameData: {{sameData}}</p> <button type='button' ng-click='showData()'>Click Me!</button>",
        scope: {
            data: "=aValue",
            theData: "@theValue",
            sameData: "&aValue",    // doesn't work. Seems only work for method.
            showData: "&showValue"
        }
    }
})

See the example in Plunker

In this example we use '=' to pass the value of an outer variable specified in an attribute in the origin markup. I.e., data: "=aValue" will create an internal variable called 'data' and get the value of the outer variable (an AngularJs $scope variable) specified in the 'a-value' attribute in the origin markup. The attribute name referred to follows the same matching pattern as the matching pattern of a directive name (i.e, 'aValue' matches 'a-value' in the origin markup).

'@' is used if we want to copy the literal value (copy the text) of an attribute in the origin markup. If we want to pass a value of an AngularJs variable then we need to use {{ . . . }} to get the value first before passing it to the directive. I.e., <scopetest the-value="{{controllerData}}" />

'&' is used to pass a function of an attribute in the origin markup.

If the attribute name being referred to is the same as the internal variable name then when defining the internal variable, we don't need to specify the attribute name after the symbol. E.g., aValue: "="; is the same as aValue: "=aValue";

When we are using isolate scope, external variables will not be available inside the directive. Only the variables that are declared inside scope: { . . . } will be available.


Transclude
This option is used to pass the matched origin markup and its inner content into a directive template. The parent-to-be element in the template needs to be decorated with ng-transclude attribute. All the inner content of the parent-to-be element will be overwritten with the passed markup. The directive also needs to set transclude: true to activate this option.

<!-- origin markup in the view -->
<trancsludetest>
  <div>
 This is a content from origin markup. 
 <br />
 Try to print a value: {{value}}
  </div>
</trancsludetest>

// code inside controller
$scope.value = 'controller value';

// directive codes
myApp.directive('transcludetest', function () {
  return {
    restrict: 'E',
    transclude: true,
    template: '<div class="fancy-class" style="border: 2px solid black; padding: 2px"><div class="another--class" style="border: 1px dashed blue" ng-transclude>content inside this div will be ignored</div></div>',
    link: function (scope, element) {
      scope.value = 'directive value';
    },
    //scope: {}   // if this is used then only external values are considered
  };
})

See the example in Plunker


Priority and Terminal
priority option is useful for directives (more than one) that are defined in a single DOM element. The option is used to determine the order of how they are going to be applied, especially for their link and compile functions. The compile and pre-link functions are executed from the greatest number while post-link functions are executed from the smallest number.

If not defined, the priority default value is 0. If the directives have same priority values then it seems that they are executed in alphabetical order.

If terminal option is used then directives that have lower priorities will be disregarded.

<!-- origin markup in the view -->
<div second-priority first-priority></div>

// directive codes
myApp.directive('secondPriority', function () {
    return {
        restrict: 'A',
        link: {
          pre: function (scope, element, attrs) {
            alert('preLink - two');
            element.append("<br/>preLink - two");
          },
          post: function (scope, element, attrs) {
            alert('postLink - two');
            element.append("<br/>postLink - two");
          }
        },
        priority: 1
    }
})
.directive('firstPriority', function () {
    return {
        restrict: 'A',
        link: {
                pre: function (scope, element, attrs) {
                  alert('preLink - one');
                  element.append("preLink - one");
                },
                post: function (scope, element, attrs) {
                  alert('postLink - one');
                  element.append("<br/>postLink - one");
                }
        },
        priority: 2,
        //terminal: true
    }
});

See the example in Plunker


Require
This option is used to pass other directive's controller into the link function of the directive where the option is specified. The other directive could be a sibling directive or a directive in one of parent elements.
The require option can take a single string or an array of strings of directive names to be found.
The string name can be:
- not prefixed - to find a sibling directive
- prefixed with '?' - return 'null' if the intended sibling directive is not found
- prefixed with '^' - find the directive in one of parent elements
- prefixed with '^?' - return 'null' if the intended directive is not found in any parent elements

<!-- origin markup in the view -->
<div parent-directive>
  <div>
 <div>
   <div sibling-directive require-test></div>
 </div>
  </div>
</div>

// directive codes
myApp.directive('parentDirective', function () {
    return {
      restrict: 'A',
      controller: function ($scope) {
        this.parentData = "<br />parentDirective data.. ";
        this.parentFunction = function(param) {
            return param + "<br />   - Hi there, this is parentDirective";
        };
      }
    };
})
.directive('siblingDirective', function () {
    return {
      restrict: 'A',
      require: '^parentDirective',
      link: function (scope, element, attrs, controller)
      {
        element.append(controller.parentData);
        var test = controller.parentFunction('<br />Hello this is siblingDirective');
        element.append(test);
      },
      controller: function ($scope) {
        this.siblingFunction = function(param) {
            return param + "<br />   - Hi there, this is your sibling directive";
        };
      }
    };
})
.directive('requireTest', function () {
    return {
        restrict: 'A',
        require: ['?^parentDirective','siblingDirective'],
        link: function (scope, element, attrs, controller)
        {
          element.append(controller[0].parentData);
          var test = controller[0].parentFunction('<br />Hello this is requireTest');
          element.append(test);
          test = controller[1].siblingFunction('<br />Hello this is requireTest');
          element.append(test);
        }
    };
});

See the example in Plunker

Thursday, 15 May 2014

Basic AngularJS Directive

Below is a basic example of using AngularJS directive:
<!--HTML markup-->
<div my-directive></div>

//JavaScript codes
var myApp = angular.module('myApp', []);

myApp.directive('myDirective', function () {
    return {
        restrict: 'A',      // possible values: A, C, E, M
        template: "{{controllerData}} <mark>This is my custom directive. '{{directiveData}}'</mark>",
        link: function (scope, element, attrs) {
            //execute a function then assign a value
            scope.directiveData = "Good morning!";
            // can change any scope value in the outside as well
            // scope.controllerData = "test";

            element.on('mouseover', function () {
                element.css('font-size', '18px');
        },
        replace: false  // remove the outer container
    };
});
restrict property is used to determine which part of origin HTML markup to be matched. The possible values are:
- A - attribute
- C - class, i.e. <div class="my-directive"/>
- E - element, i.e. <my-directive/>
- M - comment, i.e. <!--directive:my-directive-->
The values can also be combined.

template property is used to specify the markup to be added as part of the directive. The markup will be added to the existing container or replace it depending on the replace property value.
Note from the example that we can pass data that is specific to the directive or data from the controller.
If the additional markup is much then we should use templateUrl property instead.

link is used to manipulate scope variables and the directive markup (after combined with the additional markup inside template or templateUrl property if used). It accepts three required and one optional parameters:
- scope - this is the AngularJS scope object
- element - the origin element that is matched, if it is replaced then this is the new element from the template
According to AngularJS documentation, the element is actually a jqLite (a light version of jQuery library from AngularJS) wrapped element. The library contains core functionalities of jQuery and has almost identical API.
However, important to note that if jQuery library is loaded prior to AngularJS libraries then the element will be jQuery wrapped instead so it will have full jQuery functionalities.
- attrs - attributes of the origin element that is matched, if it is replaced then the attributes of the new element from the template
- controller [optional] - to pass the directive's controller instance to be accessible inside the function

On the next post, we will see more advanced examples of AngularJS directive.


References:
AngularJS Developer Guide - Directives
GitHub - AngularJS - Understanding Directives

Wednesday, 23 April 2014

Building Single Page Application with AngularJS and Web API - Part 2

On this post, we will continue building our single page application with AngularJS and Web API. For the first part of this topic, please see my previous post.

Update Functionality
Now we want to add update user functionality. First, we add a new route in our AngularJS routing configuration:
. . .
.when('/edit/:userId', {
 templateUrl: 'Partials/create-edit.html',
 controller: 'UserCtrl'
}).
. . .
Note that we use a parameter ':userId' in the path. This is used to get a value from the url and will be stored into $routeParams object. A new property called 'userId' will be created in $routeParams object (i.e. $routeParams.userId).

Other types of parameter can be used as well in a routing path:
- ':name*' is used to store all values from the path of the parameter up to the next matching string path. For example; if we set a route like '/edit/:user*/end' then when we have a url '/edit/1/type/admin/end', :user will have value '1/type/admin'
- 'name?', we can use '?' to specify that this is an optional parameter

Then add logic for updating user in our WebAPI controller:
// PUT api/UserRegistration/5
public async Task<IHttpActionResult> PutUser(int id, User user)
{
 if (!ModelState.IsValid)
 {
  return BadRequest(ModelState);
 }

 if (id != user.UserId)
 {
  return BadRequest();
 }

 db.Entry(user).State = EntityState.Modified;

 try
 {
  await db.SaveChangesAsync();
 }
 catch (DbUpdateConcurrencyException)
 {
  if (!UserExists(id))
  {
   return NotFound();
  }
  else
  {
   throw;
  }
 }

 return StatusCode(HttpStatusCode.NoContent);
}

Also add this in our AngularJS user service:
. . .
getById: function (id) {
 //return $resource('/api/UserRegistration/' + id).get();
 return $resource('/api/UserRegistration/:userId', { userId: '@userId' }).get({ userId: id });   // this is another way to build the string to be passed
},
updateUser: function (user) {
 return $resource('/api/UserRegistration/' + user.UserId, {},
  {
  customUpdate: { method: 'PUT', isArray:false }
  }
 ).customUpdate(user);
},
. . .
Notice that in updateUser function, we need to specify a custom action to invoke our Web API method. By default AngularJS $resource service has these default methods:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
Each method will invoke a call with the specified HTTP method. We need to specify an additional one with HTTP PUT method to invoke the Web API method. isArray is true if we expect the call to return an array of objects.

Then in our AngularJS user controller:
. . .
userService.getById($routeParams.userId).$promise.then(
//success
function (data) {
 $scope.user = data;
},
//error
function (response) {
 //console.log(response.status)
 $scope.error = true;
})
. . .
userService.updateUser(user).$promise.then(
 //success
 function () { $location.url('/'); },
 //error
 function () { $scope.error = true }
);
. . .

Finally, we add this link to the view:
<td><a data-ng-href="#edit/{{user.UserId}}">Edit</a></td>


Delete Functionality

Our delete function does not require a routing because it does not have its on view. The delete function will be executed on the main view.

We specify our Web API method:
// DELETE api/UserRegistration/5
[ResponseType(typeof(User))]
public async Task<IHttpActionResult> DeleteUser(int id)
{
 User user = await db.Users.FindAsync(id);
 if (user == null)
 {
  return NotFound();
 }

 db.Users.Remove(user);
 await db.SaveChangesAsync();

 return Ok(user);
}

Then in our AngularJS user service, we invoke the Web API method with $resource delete method.
. . .
removeUser: function (userId) {
 return $resource('/api/UserRegistration/' + userId).delete();
}
. . .

We add these codes as well to our controller:
. . .
$scope.remove = function (index) {
 if (confirm('Are you sure to delete this user?')) {
  //console.log(index);
  var userId = $scope.users[index].UserId;
  //console.log(userId);
  userService.removeUser(userId).$promise.then(
    //success
    function () { $scope.users.splice(index, 1); },
    //error
    function () { $scope.error = true }
   );
 }
}
. . .

Finally add this delete link to the view:
<td><a href="" data-ng-click="remove($index)">Delete</a></td>
Notice that we use $index property of ng-repeat in the view and pass it to the controller function to be able to know which particular record is being clicked. Then we can get any property's value of the record.

The complete source codes can be downloaded from here.

Monday, 24 March 2014

Building Single Page Application with AngularJS and Web API - Part 1

On this post, we will see the first part of building a simple single page CRUD application using AngularJs and Web API. The application will manage user registrations data. Complete source codes can be downloaded from here.

First we configure AngularJS routing for our views. See this post to learn more about AngularJS routing.
userApp.config(['$routeProvider',
function ($routeProvider) {
    $routeProvider
    .when('/', {
        templateUrl: 'Partials/home.html',   // this is the partial view for listing page
        controller: 'UserCtrl'
    })
    .when('/create', {
        templateUrl: 'Partials/create-edit.html',   // this is the partial view for creating user page
        controller: 'UserCtrl'
    })
    otherwise({
        redirectTo: '/'
    });
}]);

Create Functionality
Create the partial html page for creating a user.
<div>
  <span style="color:red" data-ng-show="error">An error has occured.</span>
</div>
<div>
  <label>First Name</label>
  <input type="text" data-ng-model="user.Firstname" />
</div>
<div>
  <label>Last Name</label>
  <input type="text" data-ng-model="user.Lastname" />
</div>
<div>
  <label>Organisation</label>
  <input type="text" data-ng-model="user.Organisation" />
</div>
<div>
  <label>Position</label>
  <input type="text" data-ng-model="user.Position" />
</div>
<div>
  <label>Email</label>
  <input type="text" data-ng-model="user.Email" />
</div>
<button data-ng-click="submit(user)">Save</button>
Note that there are some ng-model attributes on the input fields to instruct AngularJS to bind the value. The attributes were prefixed with 'data-' to be HTML5 compliant. ng-click attribute is also used to tell AngularJS to execute a function.

Then create our Web API method (this one is scaffoled by Visual Studio when creating a new controller):
// POST api/UserRegistration
[ResponseType(typeof(User))]
public async Task<IHttpActionResult> PostUser(User user)
{
  if (!ModelState.IsValid)
  {
    return BadRequest(ModelState);
  }

  db.Users.Add(user);
  await db.SaveChangesAsync();

  return CreatedAtRoute("DefaultApi", new { id = user.UserId }, user);
}

Now, we create our AngularJS custom service to call the Web API method:
userApp.factory('userService', ['$resource', function ($resource) {
    return {
        createUser: function (user) {
            return $resource('/api/UserRegistration').save(user);
        }
    }
}]);
Here AngularJS $resource service is used to interact with the Web API method. $resource service is useful for interacting with RESTful based services such as Web API. It is simpler to use than $http service. To use this service, ngResource module will need to be included as well in our application. In this JavaScript function, we call the save() method of the $resource service, passing user object as the argument. The service will invoke a HTTP POST call to the specified url.

Finally we create our AngularJS controller:
userApp.controller('UserCtrl', ['$scope', '$location', '$routeParams', 'userService', function ($scope, $location, $routeParams, userService) {
   
    $scope.submit = function (user) {
        $scope.error = false;        
        userService.createUser(user).$promise.then(
          //success
          function (data) { $location.url('/'); },
          //error
          function (response) { 
                         //console.log(response);
                         //console.log(response.status);
                         $scope.error = true }
        );        
    }
}]);
Here we create a submit function that calls the user service that we have just created. The submit function is called by the save button in our partial view through ng-click attribute.

Note that $promise is also used to determine what action to take if the service call is successful and if it has error. $promise is part of $resource service. If it is successful, $promise will return data object (similar to the one we passed to the service call). If it fails, it will return a HTTP response object. It might be useful to see the headers and status properties of the response object.

$scope.error variable is used to show an error message if an error has occurred. This variable is referred to by ng-show in our partial view.


Listing Functionality
We have already implemented the create user functionality, now let us do the listing function.

First, create the partial view.
<div>
    <span style="color:red" data-ng-show="error">An error has occured.</span>
</div>
<table>
    <thead>
        <tr>
            <th>Firstname</th>
            <th>Lastname</th>
            <th>Email</th>
        </tr>
    </thead>
    <tbody ng-repeat="user in users">
        <tr>
            <td>{{ user.Firstname }}</td>
            <td>{{ user.Lastname }}</td>
            <td>{{ user.Email }}</td>
        </tr>
    </tbody>
</table>

Then the Web API method:
// GET api/UserRegistration
public IQueryable<User> GetUsers()
{
  return db.Users;
}

Add our user service with this method:
getAllUsers: function () {
  return $resource('/api/UserRegistration').query();
}
Here we use the $resource service's query() method that will invoke a HTTP GET call.

Then add the following codes in our controller:
$scope.init = function () {
  // Get all users
  userService.getAllUsers().$promise.then(
    //success
    function (data) {
      $scope.users = data;
    },
    //error
    function (response) {
      //console.log(response);
      //console.log(response.status);
      $scope.error = true;
    }
  );
}

In the coming post, we will see the edit and delete functionality.

Wednesday, 19 February 2014

Routing in AngularJs

On this post we will see the basic of how to create Single Page Application with AngularJs.

First we need to add reference to AngularJs routing library.
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.min.js"></script>

Then we add dependency to ngRoute module in our application module.
var myApp = angular.module('myApp', ['ngRoute']);

Next, use $routeProvider service that will be available after we include the new module to configure the routes that we have. The basic syntax is as follow:
$routeProvider.when('desired_path'), {
    templateUrl: 'location_of_the_partial_view_file',
    controller: 'controller_name_for_this_partial_view'
}
The path can contain route parameter(s) which is specified with colon (:) and could end with a star (*). Also we could have an optional parameter with a question mark (?). For more information, please see $routeProvider documentation.

Below is an example of a routes configuration:
myApp.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
    .when('/pageOne', {
        templateUrl: 'partials/page-one.html',
        controller: 'PageOneCtrl'
    })
    .when('/pageTwo', {
        templateUrl: 'partials/page-two.html',
        controller: 'PageTwoCtrl'
    })
    .otherwise({
        redirectTo: '/'
    });
} ]);

Finally we use ng-view directive to apply the configuration in our main view. For example:
<div data-ng-view></div>

Below is an example of the complete main view:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="myApp">
<head>
    <title></title>
    <script src="http://code.angularjs.org/1.2.9/angular.min.js" type="text/javascript"></script>
    <script src="http://code.angularjs.org/1.2.9/angular-route.min.js" type="text/javascript"></script>
    <script src="Scripts/app.js" type="text/javascript"></script>
    <script src="Scripts/Home/page-one-controller.js" type="text/javascript"></script>
    <script src="Scripts/Home/page-two-controller.js" type="text/javascript"></script>
</head>
<body>
    <a href="#">Home</a> | <a href="#pageOne">Page One</a> | <a href="#pageTwo">Page Two</a>
    <div data-ng-view></div>
</body>
</html>

If we want to use HTML5 url mode that is supported by recent browsers, on myApp.config(...) method add a dependency to $locationProvider service then add this line inside the method:
$locationProvider.html5Mode(true)

Friday, 7 February 2014

Getting Started with AngularJS

On this post we will see a simple example of an AngularJS application.

First we need to reference the library on our application. We could copy the files into our project or use the Angular CDN http://code.angularjs.org/

Then create a module. Using module is not required but it is useful to have better code organisation and for reusability.
angular.module('myApp', []);
The square brackets on the second argument is for specifying any dependencies required. At the moment we don't have any.

Next create a controller:
angular.module('myApp').controller('GreetingCtrl', ['$scope', function ($scope) {
    $scope.greeting = 'Hola!';

    $scope.echoThis = function (value) {
        var processedWord = "";
        if (value) {
            processedWord = 'Echo ' + value;
        }
        return processedWord;
    };

    $scope.print = function (value) {
        $scope.result = $scope.word + value + " is printed";
    };
} ]);
Note that we use angular.module('myApp') to retrieve our module that we have created. If we have used angular.module('myApp',[]) instead, this would have recreated 'myApp' module again thus overwrited the previous module declaration. Use angular.module('myApp').controller() to define a controller inside a module.

We have also used an inline dependency injection to provide $scope service to the controller. To inject one or more components using inline annotation, we just need to put square brackets around the function, specify the components before the function and put the referred components in the same order in the function's arguments. For example:
['dep1', 'dep2', 'depN', function(dep1, renamedDep2, depN){ ... }]
Note also that the argument names can be different than the specified component names as long as they have the same order. $scope is a built-in Angular service that in simple term can be said similar to a global container object that has properties and/or functional properties (have methods attached). $scope properties will be available on the views. Line 1 shows a normal property while line 4 and 12 show functional properties.

Then we create our view:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="myApp">
<head>
    <title></title>
    <script src="http://code.angularjs.org/1.2.9/angular.min.js" type="text/javascript"></script>
    <script src="Scripts/app.js" type="text/javascript"></script>
    <script src="Scripts/Home/greeting-controller.js" type="text/javascript"></script>
</head>
<body>
    <span>{{ "Hello" + " World"}}</span>
    <div data-ng-controller="GreetingCtrl">
        {{ greeting }}
        <br /><br />
        <input data-ng-model="word" /> {{ echoThis(word) }}
        <br />
        <br />
        <button data-ng-click="print(' some text ')">Print</button>
        {{ result }}
    </div>
</body>
</html>
We have some attributes (which they called directives) in our view; ng-app is used to bootstrap AngularJs and the value is used to specify the root module to be used in the view, ng-controller to specify which controller to use for that particular section of the view, ng-model to bind input value and ng-click to execute a function when the element is clicked.

If you notice I have put the first code snippet on this post (for creating the application module) inside app.js file and the controller codes inside greeting-controller.js file.


Further reading:
Code Organization in Large AngularJS and JavaScript Applications
AngularJS Dependency Injection