Month: February 2015

Throw exceptions with line number in JavaScript

There might be some scenarios that we need to throw exceptions in JavaScript, and get the line number, and the call stack, specially when we are developing a feature that will be used by other developers. Since JavaScript have far less tools to aid in debugging than other languages, when we are building a functionality it is handy to throw an exception when the developer that is using you code need to meet certain requirements to let them know when have been a violation in the code in the logic.

throw exceptions

This is widely used when we use the network to do the communication and transmit the data with the back-end, and the connection fails and we want to show specifically where in the code the error happened (code line). Especially when the component you are developing takes thousand of code lines. Or when we want to force the consumed of our component to specify a specific type of object. Let's see the following example.

Throw exceptions example:

function someFunction(callback){
    if(typeof callback != ‘function’){
        // throw an exception here
    }else{
        callback();
    }
}

 

javascript book

Book Tip

Speaking JavaScript: An In-Depth Guide for Programmers
Like it or not, JavaScript is everywhere these days—from browser to server to mobile—and now you, too, need to learn the language or dive deeper than you have. This concise book guides you into and through JavaScript, written by a veteran programmer who once found himself in the same position.

Amazon

 

With this code we can achieve it:

var err;
try {
throw new Error('myError');
} catch (e) {
err = e;
}
if (!!err)
console.log(err.stack);

if you put this code in the console (chrome) this is the result:

Continue reading "Throw exceptions with line number in JavaScript"

Optimizing code using Object.defineProperty instead of $scope for $watch in AngularJs

It is all about performance

No long ago I wrote an article about “KnockoutJs computed equivalent in AngularJs”. In that article I pointed that the Angular equivalent of a KnockoutJs computer is the $scope.$watch() service. angularjs performance defineProperty

With the pass of the time, I discovered that using $watch in angular can affect the performance of the application, so I was wondering if there is an alternative to $watch to improve the performance of an application specially if it is a large application...

The answer is yes, there is an alternative to $watch.
Note:
It is using Object.defineProperty(), when you planning to use defineProperty, you have to keep in maind that it is supported only by Internet Explorer 9 and above.

First thing first:

To achieve this we will need to use the "controller As" syntax instead of injecting the $scope.
Although The "Controller As" syntax is basically your controller published to the $scope (this syntax is supported by Angular 1.2 and above), here are some reasons to use the "Controller As" syntax over the $scope syntax:

(from John Papa Angular style guide):

Use the controllerAs syntax over the classic controller with $scope syntax.

Why?: Controllers are constructed, "newed" up, and provide a single new instance, and the controllerAs syntax is closer to that of a JavaScript constructor than the classic $scope syntax.

Why?: It promotes the use of binding to a "dotted" object in the View (e.g. customer.name instead of name), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting".

Why?: Helps avoid using $parent calls in Views with nested controllers.

<!-- avoid -->


<div ng-controller="Customer">
    {{ name }}
</div>


<!-- recommended -->


<div ng-controller="Customer as customer">
    {{ customer.name }}
</div>


 

book

Book Tip

ng-book - The Complete Book on AngularJS
Ready to master AngularJS? What if you could master the entire framework – with solid foundations – in less time without beating your head against a wall?


Amazon

 

Using defineProperty instead of the angular $watch service, to watch a property.

In general, when we going to need to use a $watch?
A: Whenever we need to subscribe to and object and observe when the value change and trigger an action as a response to that change.

Advise: In general, using $watch in controllers is something to be avoided whenever possible.

Here is a simple example of how to implement defineProperty:

Object.defineProperty(myController.prototype,
    'controllerPropertyName', {
    get: function () {
        return this._personName;
    },
    set: function (newValue) {
        this._personName = newValue;
        //Call method on update here
    },
    enumerable: true,
    configurable: true
});
}

To make this works in angular we will need to wrap the defineProperty within a service:

var myApp = angular.module('myApp', []);
myApp.service('efficientWatch', efficientWatch);

function efficientWatch() {
    this.watch = function (name, controllerProto, func) {
        Object.defineProperty(controllerProto,
        name, {
            get: function () {

                return this._personName;
            },
            set: function (newValue) {
                this._personName = newValue;

                //Call method on update
                if (typeof func == 'function') func(newValue);

            },
            enumerable: true,
            configurable: true
        });
    };
};

You can see the code working together here.
http://jsfiddle.net/ks5et82p/176/

Prevent ng-click action on hitting enter

logo-angularjs

I was doing a functionality in the project I’m currently working, I captured the onKeypress event to capture the enter key when the user finish editing in a form, I also had a button to do another action with an ng-click directive, something like this code:

 

Try This:

I’m currently writing a post about it because I thought it was a bug in the angular core functionality or some code I had written in other place within the application(it wasn't, I'll explain later), and it was affecting then my functionality. I was trying to figured out by myself before I search for this problem in internet.

 

book

Book Tip

ng-book - The Complete Book on AngularJS
Ready to master AngularJS? What if you could master the entire framework – with solid foundations – in less time without beating your head against a wall?


Amazon

 

The first thing that came to my mind was to do a directive to capture the enter key in the button and dismiss it

Continue reading "Prevent ng-click action on hitting enter"

$watch deep Data Structures in AngularJs

$watch a collection can be quite a challenge, this can be done in several ways ($watch, $watchCollection, $watchGroup).
our challenge was to find a solution for watching a tree structure that contains nodes with cyclic references.

The Challenge

Let’s say each tree node has parent and children references attached to it (to make traversing the tree as simple as possible). Each node will also contain a value property that links to the actual data. Thus, each node might look similar to this:

$scope.node = {
  value: { /* data */ },
  parent: { /* another node */ },
  children: [ /* list of more nodes */ ]
};

How would you watch this data structure from your controller, so that changes to the node value will call a function?

Possible solution?

the first thought was, just watch it:

$scope.$watch('node', function () {
  // do something
});

this code doesn’t yield any error and it looks simple
Unfortunately the watcher will not get triggered when a nested property from within the value object is changed.
This is because $watch will only shallow check the referenced value by default.

Continue reading "$watch deep Data Structures in AngularJs"

Promises examples in JQuery, Angular and Protractor

The JavaScript promises are one of the hardest subjects to learn from javascript. It is not the intent of this post to explain in deed what a promise is, we just gonna touch the basics, and see some examples of how to create our own promises with JQuery, AngularJs and Protractor

Topics:

  • Briefly explain what promises are
  • Promise examples
  • JQuery promise example
  • AngularJs/$q promise example
  • Protractor promise example
  • Working example in jsFiddle

What is a promise

A promise represents the eventual result of an asynchronous operation like a network call or a setTimeout function. It is a placeholder into which the successful result value or failure will materialize in a differed call.

Continue reading "Promises examples in JQuery, Angular and Protractor"

AngularJs parse example Directive

To illustrate this AngularJs parse example Directive in this example we are going to create a directive that allows you to create editable elements. Such technique is also known as click-to-edit or edit-in-place.

First, when should I use Directives in AngularJs?
Any time you need to alter the DOM, Insert, Delete, Modify a node, add an event handler, etc.
If you are using JQuery within a controller or within a Service you’re doing it wrong, That logic needs to be moved to a Directive.

AngularJs parse example

The directives enable the re-utilization of the code (applying the DRY principle).

Example:

This directive, what it does is, it substitute the text inside a container for an Html input text (the text become editable). That’s why I called this Directive “edit-in-place”:

 .directive('editInPlace',['$parse', '$timeout', function ($parse, $timeout) {
            return {
                scope: {
                    editInPlace: '=editInPlace',
                    onDone: '&onDone'
                },
                link: function (scope, element, attrs) {

                    element.parent().append('<span class="edit-in-place-span" >' + scope.editInPlace + ' </span>');
                    var $editSpan = element.parent().find('span.edit-in-place-span');

                    //we are using bootstrap icon-ok for the Done button
                    element.parent().append('<span class="edit-in-place-edit-wrapper">
                    <input type="text" class="edit-input" value="' + scope.editInPlace + '" />
                    <i class="icon-ok edit-in-place-done"></i></span>');
                    var $editInput = element.parent().find('.edit-in-place-edit-wrapper');
                    $editInput.hide();

                    element.parent().find('span.edit-in-place-span').click(function (e) {
                        if ($editInput.is(":visible")) {
                            //read only mode
                            $editInput.hide();
                            $editSpan.show();
                        } else {
                            //edit mode
                            $editInput.show();
                            $editInput.find('input').focus().select();
                            $editSpan.hide();
                        }

                    });

                    element.parent().find('i.edit-in-place-done').click(function (e) {
                        scope.editInPlace = element.parent().find('input.edit-input').val();

                        $timeout(function() {
                            //this is to be able to assign the changes back to the source
                            var parsed = $parse(attrs.editInPlace);
                            //used scope.$parent
                            parsed.assign(scope.$parent, scope.editInPlace);
                        });

                        $editSpan.text(scope.editInPlace);
                        $editInput.hide();
                        $editSpan.show();
                        if (typeof scope.onDone == "function") {
                            scope.onDone(); //this is the callback called when finished to edit
                        }
                    });

                },
            }
        }]);

Let's analyze the code:

Notice the way we inject the dependencies:

        .directive('editInPlace', ['$parse', '$timeout', function ($parse, $timeout) {

This is a best practice that will helps you to avoid errors when you minify/compress the code, because the anonymous function parameters become something like this:

function(a,b){} so when you reference in your code $parse or $timeout it will throw an error. That’s why Angular provides the option to pass it as string.

In the isolate scope we have two variables:

   scope: {
      editInPlace: '=editInPlace',
      onDone: '&onDone'
          },

We are explicitly expecting the scope.editingInPlace variable as a value (notice the = symbol): '=editInPlace', and onDone as a function (notice the & symbol).

editingInPlace will be the value we going to modify.
and onDone will be the callback function we going to call when finished editing.

We are going to use the $parse service to parse the attrs.editInPlace attribute and be able to modify the scope variable.

With the $parse service we can convert Angular expression into a function/objects, in this case we going to convert scope.editInPlace expression into an object

  //note: this code is a getter
  var parsed = $parse(attrs.editInPlace)(scope);

  //and this code is a setter
  //this is to be able to assign the changes back to the source
  var parsed = $parse(attrs.editInPlace);
  //used scope.$parent
  parsed.assign(scope.$parent, scope.editInPlace);

 

 

book

Book Tip

ng-book - The Complete Book on AngularJS
Ready to master AngularJS? What if you could master the entire framework – with solid foundations – in less time without beating your head against a wall?


Amazon

 

Here is a working example:

 

This directive works perfect. Now, this doesn't mean that this is the best approach used for this AngularJs parse example (we will still using the parse service for this example).

sphagetti-code directive AngularJs parse example

In this specific example the directive uses a lot of JQuery code, winch is not a good practice at all, specially when you can achieve the same result using the "angular way".
This should be the result of rewrite the directive to the angular way:

myApp.directive("editInPlace", function() {
        return {
            restrict: 'A',
            scope: true,
            template: [
                '
<div ng-switch="edit.editing">',
                    '
<div ng-switch-when="true">',
                        '<input type="text" ng-model="edit.value" />',
                        '<button ng-click="edit.toggleEdit()">Done</button>',
                    '</div>

',
                    '<span ng-switch-default ng-click="edit.toggleEdit()">{{ edit.value }}</span>',
                '</div>

'
            ].join(""),
            controller: function($scope, $attrs, $parse) {
                var edit = this;
                edit.editing = false;
                edit.value = $parse($attrs.editInPlace)($scope);
                edit.toggleEdit = function() {
                    debugger
                    edit.editing = !edit.editing;
                    
                    //you can use either $scope.$eval or $parse to update de object 
                    //$scope.$eval([$attrs.editInPlace , "=", JSON.stringify(edit.value)].join(""));
                    $parse($attrs.editInPlace).assign($scope, edit.value);
                };
            },
            controllerAs: "edit"
        };
    });

 

You can try the full working example of the parse here:

This directive was tested with AngularJs version 1.3.3

If you have any question about this AngularJs parse example, do not hesitate to ask in the comments of this blog, or on twitter. 😉

Best practice to include code within the cycle digest in AngularJs

I was converting a DurandalJs (using BreezeJs for the async calls) application to AngularJs, the team decided to keep using BreeseJs with AngularJs, so I started notice that when I update a $scope variable (to update the view) the change wasn’t reflecting in the view.
I realized that the problem was that when you try to update an $scope variable when a promise come back, this operation is done outside the angular digest cycle, and that’s why it was not updating the view.
This only happens when you deffer a call outside Angular (you can prevent this using the $http and $q services).

The first solution I came across, was to call $scope.$apply(). But I start receiving this error:
Error: $digest already in progress

It means your $scope.$apply() isn't high enough in the call stack (digest cycle).

I kept looking and I found this code.

if(!$scope.$$phase) {
   //$digest or $apply
}

Continue reading "Best practice to include code within the cycle digest in AngularJs"

KnockoutJs computed equivalent AngularJs

Recently, I had to work in a project, where I had the opportunity of convert a DurandalJS (KnockoutJs) application into AngularJs, and I faced a couple of challenges that I would like to share with you:
KnockoutJs computed equivalent AngularJs

The Subscribe:

First challenge was to find the Angular equivalent of a knockout observable subscribe:
this was get from the Knockoutjs documentation:
http://knockoutjs.com/documentation/observables.html

var myViewModel = {
    personName: ko.observable('Bob')
};

myViewModel.personName.subscribe(function(oldValue) {
    alert("The person's previous name is " + oldValue);
}, null, "beforeChange");

Continue reading "KnockoutJs computed equivalent AngularJs"

ng-repeat onFinishRender directive AngularJs

There are some specific scenarios specially when you manipulate the DOM with ng-repeat directive. Lets imagine we have a code that prints a list of element using an ng-repeat. In your controller you have a code to instantiate a bootstrap tooltip for all the elements that are going to be rendered when the ng-repeat is compiled by AngularJs. As a best practice it is better to place this type of code in a directive, for this example purpose, we are going to keep it simple and leave it in the controller.

$('.yourDynamicallyCreatedElements').tooltip("text")

 
onFinishRender directive AngularJs

onFinishRender directive AngularJs

The problem here is that the code within the controller is executed before angular compiles the ng-repear, before the DOM elements are part of the HTML. It is hard if not impossible, to find a place to bind events to the elements of an ng-repeat, since angular doesn't provide any event that fires when the elements finish rendering. Here we are going to share haw to create an event onFinishRender directive.

I created this simple directive to capture the moment that the last element is inserted in the DOM,  with this we will be able to call a JavaScript method after the ng-repeat completes the rendering process.

this is the View:

<ul>
  <li ng-repeat="item in items" on-finish-render="callMyCustomMethod()">
      dummy Text
  </li>
</ul>

 
 

Here is the onFinishRender directive:

 

.directive('onFinishRender',['$timeout', '$parse', function ($timeout, $parse) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                    if(!!attr.onFinishRender){
                      $parse(attr.onFinishRender)(scope);
                    }
                });
            }
        }
    }
}])

Continue reading "ng-repeat onFinishRender directive AngularJs"

Installing Protractor with npm in windows environment behind a proxy

Installing Protractor npm windows environment behind proxy
In this post we going to assume that you know what is Node, npm, etc so we don't going to explain this.

Installing Protractor npm windows environment behind proxy

First we need to install or update NodeJs (npm comes with node now), you can click here to get the latest version.

We need to setup the npm to work behind a proxy so we can run protractor:

Run this commands in a console, for http and https

npm config set proxy http://proxy.company.com:8080
npm config set https-proxy http://proxy.company.com:8080

 

If you have to set username and password:

http://username:password@proxy.company.com:8080

if your password have an @ then surround it in quotes

http://"username:your@password"@proxy.company.com:8080

To reset proxy for npm:

npm config rm proxy
npm config rm https-proxy

To get the proxy settings for npm:

npm config get proxy
npm config get https-proxy

Quick notes to Setup Protractor

Use npm to install Protractor globally with:

npm install -g protractor

This will install two command line tools, protractor and
webdriver-manager. Try running
protractor --version to make sure it's working.

The webdriver-manager is a helper tool to easily get an
instance of a Selenium Server running. Use it to download the necessary
binaries with:

webdriver-manager update

Now start up a server with:

webdriver-manager start

This will start up a Selenium Server and will output a bunch of info
logs. Your Protractor test will send requests to this server to control
a local browser.

 

Configuration

Create a file called protractor-conf.js in the test directory and add the following configuration to it.

The Selenium webdriver has the ability to execute tests against multiple browsers concurrently, making cross-browser testing easy. Protractor has a sample config file available with all the configuration options.

If you installed Protractor locally, be sure to set the seleniumServerJar and chromeDriver options with the location of these files.

exports.config = {
// location of the Selenium JAR file and chromedriver, use these if you installed protractor locally
// seleniumServerJar: '../node_modules/protractor/selenium/selenium-server-standalone-2.40.0.jar',
// chromeDriver: '../node_modules/protractor/selenium/chromedriver',// location of your E2E test specs

specs: [
  '../test/e2e/*.js'
],// configure multiple browsers to run tests
multiCapabilities: [{
'browserName': 'firefox'
}, {
'browserName': 'chrome'
}],// or configure a single browser

/*
  capabilities: {
   'browserName': 'chrome'
 }
  */
// url where your app is running, relative URLs are prepending with this URL
baseUrl: 'http://localhost:9000/',


// testing framework, jasmine is the default</i>
framework: 'jasmine'
};

Notice that the baseUrl does not determine the location of your app. It just determines relative URLs. If you call browser.get(‘/’) in your Protractor tests, this will redirect to your baseUrl.

Hope this was helpful 😉