Wednesday, November 11, 2015

ReactJS and jQuery tweetbox comparison

Using jQuery

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div class="well clearfix">
      <textarea class="form-control"></textarea><br/>
      <button class="btn btn-primary pull-right">Tweet</button>
  </div>
</body>
</html>

// Initially disable the button
$("button").prop("disabled", true);

// When the value of the text area changes (using input event that works on modern browsers)
$("textarea").on("input", function() {
  // If there's at least one character...
  if ($(this).val().length > 0) {
    // Enable the button.
    $("button").prop("disabled", false);
  } else {
    // Else, disable the button.
    $("button").prop("disabled", true);
  }
});

-------------------------------------------------------------------------------------------------------------------------

Using React 
There is no markup in the HTML. Instead Markup and Behavior are together in JavaScript code!

<!DOCTYPE html>
<html>
<head>
<script src="//fb.me/react-with-addons-0.13.3.js"></script>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  <title>JS Bin</title>
</head>
<body>
</body>
</html>

//JSX(React)
var TweetBox = React.createClass({
  getInitialState: function() {
    return {
      text: ""
    };
  },
  handleChange: function(event) {
    this.setState({ text: event.target.value });
  },
  render: function() {
    return (
      <div className="well clearfix">
        <textarea className="form-control" onChange={this.handleChange}></textarea>
        <br/>
        <button className="btn btn-primary pull-right" disabled={this.state.text.length === 0}>Tweet</button>
      </div>
    );
  }
});

React.render(
  <TweetBox />,
  document.body
);

--------------------------------------------------------------------------------------------------------------------

  • In jQuery, you write event handlers which modify the DOM.
  • In React.js, you write event handlers which modify the state. And you write render() to reflect the current state
  • We used input event for jQuery, but in React we use onChange - you'll learn about how events differ in React's JSX from React's documentation, so don't worry too much now.
  • More importantly, we use {...} syntax to include any JavaScript code inside the HTML syntax part of JSX. In this case, we want to pass the handler handleChange, and we prefix it with this. because it's a method on this UI object.
  • If you're used to jQuery, this might seem like a bad practice, but don't worry. Again, in large applications, the code will be more manageable if those markup and behaviors are kept together for each piece of UI!!
--------------------------------------------------------------------------------------------------------
To read more, follow the link
http://reactfordesigners.com/labs/reactjs-introduction-for-people-who-know-just-enough-jquery-to-get-by/

Sunday, October 25, 2015

JavaScript - Changing Prototype dynamically

JavaScript prototype inheritance

/* We can change the prototype of a class in the prototype chain dynamically. Not that this may be a good idea at all. */
//Define a Parent class
function Parent(){
    this.someProperty = "Some Property";
}
//Extend Parent's prototype
Parent.prototype.someMethod = function(){
    console.log("Some Method");
}
//Define Child class, making sure Parent's ctor is called
function Child(){
    Parent.call(this);
}
//Extend Child's prototype
Child.prototype.someOtherProperty = "Some other property";
//Change the Child's prototype here to the Parent's prototype
Child.prototype = Object.create(Parent.prototype);
var child = new Child();
child.someMethod(); // "Some Method"
console.log(child.someProperty); // "Some Property"

console.log(child.someOtherProperty); //undefined
-----------------------------------------------------------------------------------------

Property lookups through the JavaScript prototype chain work as follows:
  • If the object has a property with the given name, that value is returned. (The hasOwnProperty method can be used to check if an object has a particular named property.)
  • If the object does not have the named property, the object’s prototype is checked
  • Since the prototype is an object as well, if it does not contain the property either, its parent’s prototype is checked.
  • This process continues up the prototype chain until the property is found.
  • If Object.prototype is reached and it does not have the property either, the property is considered undefined.
Understanding how prototypal inheritance and property lookups work is important in general for developers but is also essential because of its (sometimes significant) JavaScript performance ramifications. Most JavaScript engines use a dictionary-like data structure to store object properties. 


Each property access therefore requires a dynamic look-up in that data structure to resolve the property. This approach makes accessing properties in JavaScript typically much slower than accessing instance variables in programming languages like Java and C#.

For further reading, http://www.toptal.com/javascript/javascript-prototypes-scopes-and-performance-what-you-need-to-know

Tuesday, July 28, 2015

Ad hoc queries and Plan Cache Pollution

Just sharing a link on why we should not issue random ad hoc queries against Production - pollutes the plan cache...I have seen instances when a random ad hoc report query run by a developer brought down Production to its knees...


http://blog.sqlauthority.com/2010/08/28/sql-server-plan-cache-retrieve-and-remove-a-simple-script/

Excerpts:
Query that demonstrates cache plans which are ‘ad hoc’ or called only once in a life time.

SELECT 
    [text]cp.size_in_bytesplan_handle
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE cp.cacheobjtype N'Compiled Plan'
   AND cp.objtype N'Adhoc'
   AND cp.usecounts 1
ORDER BY cp.size_in_bytes DESC;

You can see how much memory is already bloated by not-so-useful queries. If you want to remove any large plan cache which you do not think is useful to you, you can run the following command to remove it:

DBCC FREEPROCCACHE(plan_handle)

Note: Do not play with this settings on production server unless you know what you are doing.

Friday, June 5, 2015

How to enable OData in Web API

ASP.NET Web API supports OData queries out of the box for all your complex data querying needs using the Web Service. There are just three steps you need to do to implement it. Make sure you install the OData nuget package though first.

1) Use the attribute [EnableQuery()] to decorate the targeted Web API end point

2) Make sure you return IQueryable (not IEnumerable or any other variant) from the REST end point

3) Add AsQueryable() at the end of your LINQ query so it can return the items as IQueryable.

Example:

[EnableQuery()]
public IQueryable<Order> Get()
{
    return orderRepository.Retrieve().AsQueryable();
}


And that's it. You can skip, sort, take, filter and do all the things you need to shape your queries for returning your data to your UI in the manner you like. Of course, you need to use the OData query syntax from your UI code to hit the endpoints. All in all, a very simple API to learn and implement, rather than trying to roll out your own custom filtering, sorting et al code.

Thursday, June 4, 2015

ASP.NET Web API Authentication from Angular

When a user logs in to be authenticated by issuing a POST request from the browser using the default Authorization Service provided by ASP.NET Web API, the POST message is not in JSON format but URL encoded like so

userName=xyz%40domain.com&password=foo_Bar&grant_type=password

This necessitates that if we use the $resource RESTful service to hit the Authorization service /token endpoint, we need to convert the JSON message format that $resource spits out to match this URL encoded format.

To do this, we need to do two things

1) Specify in the POST Request Header that the Content-Type is URL encoded like so
                
             Content-Type = application/x-www-form-urlencoded

2) Transform the JSON to URL encoded format using the transformRequest property of $resource. See code snippet

(function(){
    angular.module('common.services')
                .factory('userService',
                              ['$resource', 'appConfigs', userService]);

    function userService($resource, appConfigs) {
         return {
              register: $resource(appConfigs.serverURL + '/api/Account/Register', null,
                                {
                                    'registerUser' : { method: 'POST'}
                                }),
              login: $resource(appConfigs.serverURL + '/token', null,
                           {
                              'loginUser': { 
                                  method: 'POST',
                                  headers:{'Content-Type':'application/x-www-form-urlencoded'},
                                  transformRequest: function(data, headersGetter) {
                                      var str = [];
                                      for (var s in data)
                                         str.push(encodeURIComponent(s) + '=' +
                                                       encodeURIComponent(data[s]));

                                     return str.join('&');                                              
                            })
        };
    }
})();

Once we successfully call this endpoint from the login button, we grab and store the access token returned from the Authorization Service, thereby allowing us to pass the token along for future requests.

var user = {};
....

vm.login = function() {
   vm.user.grant_type = 'password';
   vm.user.userName = vm.user.email;

   userService.login.loginUser ( vm.user,
          function(data) {
              vm.isLoggedIn = true;
              vm.message = '';
              vm.password = '';
              vm.token = data.access_token; //SAVING TOKEN HERE!!
          },
         //add response.data.error callback message to the vm.user.message property
        ....
    );
};

Enabling CORS in your Web API

The same origin policy enforced in browsers as a defense against cross-site request forgery (CSRF) attacks has traditionally prevented a browser from calling an API method deployed in a separate domain or server from which the web application originated and is hosted.

But there are scenarios where you want your API to be accessible across domains - say internally across applications or if you are serving your Web API as a public API.

Before the advent of CORS (Cross Origin Resource Sharing), developers worked around this using JSONP (P for padding which implies the returned JSON needs to be parsed before deserializing it). JSONP makes use of calling the Web API over an http endpoint using a src attribute inside a <script> tag as <script> tags are allowed cross domain.

But JSONP is more like a hack and now modern browsers support CORS. To Enable CORS is very easy. Download the Nuget package for CORS and in your configuration setup in WebApiConfig.cs, make an entry as

      config.EnableCORS();

And then as an example, just mark your controller class or GET action methods in your Web API with

      [EnableCorsAttribute("http://localhost:52347", "*", "GET")]

The three parameters can be a list of comma separated values or * (for all). The first parameter is for the list of valid origins (the origin of the client apps that will be accessing the API), the second for the list of allowed headers and the third for a list of allowed HTTP methods.

Trivia:

1) IE will not treat a different port where your Web Service is deployed as a different domain in your local environment. But when it is deployed in separate servers, then it will enforce the same origin policy.

2) Use JsonFormatter's ContractResolver in the WebApiConfig.cs file to keep your C# property names as PascalCase and JSON properties as CamelCase so you don't have to compromise on best practices on either end.

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
           new CamelCasePropertyNamesContractResolver();

Redis hash - To be or not to be

The primary data structure used by Redis to optimize memory utilization is the hash. When storing your object in  a hash, you hash individual fields and store it with a hash. By using HMSET, you can set multiple fields using a hash in a single command. In implementation speak, the hash is actually a function that takes a parameter and hashes it - a good algorithm for the function would avoid hash collisions.

Now, why go through the extra effort of creating a hash and storing individual fields of the object with the hash, rather than storing the object as a single key value structure which makes it simpler to serialize/deserialize from JSON to your POCO objects? The answer is performance and yes, memory efficiency too.

With a hash, you are indexing the field and you can get to the value of a particular field of your object (stored with the hash) very quickly - not so if you are storing the whole object in just one KV pair.

So the bottom line is, if you need to read/write specific properties frequently within your object, consider storing it as a hash. If the object is retrieved most of the time as a whole, you can just store it as a simple string key value pair.

Note that the default C# driver as of today does not use hashes for storing objects by default.

For more reading on this topic, go to
http://redis.io/topics/memory-optimization

For an excellent blog on the five different data structures in Redis, go to
http://openmymind.net/2011/11/8/Redis-Zero-To-Master-In-30-Minutes-Part-1/

Wednesday, June 3, 2015

Using $httpBackend to mock up E2E Web Service API

Define a module in your cross cutting common services folder to set up the mock interceptor to the backend web services. This module would be injected as a dependency in your main module, and commented out when the actual RESTful API is available. Note that Angular has ngResource that makes it easy to work with a RESTFul API.

In the mocking module, do something like this:

var orders = [
       {
           orderId : 1,
           orderDate : Date.now(),
           totalPrice: 45.89,
           category : "online"
       },
       {
           orderId : 2,
           orderDate : Date.now(),
           totalPrice: 35.55,
           category : "in-store"
       },
       //more order objects
];

var orderUrl = "/api/orders";

//get all Orders
$httpBackend.whenGET(orderUrl).respond(orders)

//get single Order - use a regex
var editingRegex = new RegExp(orderUrl + "/[0-9][0-9]*", '');

$httpBackend.whenGET(editingRegex).respond( function(method, url, data)
    var order = { orderId: 0 };
    var parameters = url.split('/');
    var length = parameters.length;
    var id = parameters[length - 1];

    if (id > 0) {
        for (var i=0;i<orders.length;i++) {
              if (orders[i].orderId === id) {
                   order = orders[i];
                   break;
       };
    }
    return [200, order, {}];
);


//Save or edit an order
$httpBackend.whenPOST(orderUrl).respond(function (method, url, data) {
      var order = angular.fromJSON(data);
       
      if (!order.orderId) { //new order
          order.orderId = orders[orders.length - 1].orderId + 1;
          orders.push(order);
      }
      else { //update order
          for (var i=0;i<orders.length;i++) {
                if (orders[i].orderId === order.orderId) {
                    orders[i] = order;
                    break;
                 }
          };
      }
      return [200, order, {}];

});

//Ignore any other assets the app needs that we should not be intercepting
$httpBackend.whenGET("/app/").passThrough();


Voila! Using this mockup, the application will add new Orders to the in-memory array of Orders without the need to touch a backend API.

For more details, read up
https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend

Tuesday, June 2, 2015

SQL CE Index is not populated during a batch insert

Discovered a strange behavior with SQL CE (version 3.0) in a handheld mobile application the other day. One of the tables had a million+ rows with an index on the correct column for the query, but it was taking a few minutes to return the results.

The table was used as a template table with 0 rows to start with and then the million+ rows inserted into the table as part of the application logic. Though the index exists, it was discovered to be empty while running the command

                 sp_show_statistics 'table_name', 'index_name'


TABLE    INDEX                     ROWS    ROWS_SAMPLED    STEPS     DENSITY
Item      UQ_Item_Index       0           0                          0            0


The solution was to drop the index and create it after the rows are inserted in the application logic.
Once this change was made, the result returned in less than 1 second. There are a lot of peculiarities with the SQL CE database because of its limitations and I guess this is one of them.
Apparently the index is not populated if it exists already on an empty CE table, unless it is created after some data is inserted in the table.

TABLE    INDEX                    ROWS        ROWS_SAMPLED    STEPS    DENSITY
Item      UQ_Item_Index    1129454      1129454                200        8.853835E-07

Unit Test scaffolding with Jasmine

To run JavaScript Unit tests using the Jasmine Testing framework, install Jasmine as a Node plugin. Once installed it can also be incorporated as part of your build process and run as a task on each build. One can also download Jasmine directly and install it, rather than use NPM. Doing so as a standalone comes  with it a html page SpecRunner.html. This html file loads the testing framework, the javascript files that need to be tested and executes the tests.

By convention, for your test files create a "spec" folder and name your test files like test1.spec.js where test1 can be any appropriate name for your test.

Use the snippet of a unit test specification to create the specs. Note the use of nested describe functions to group a set of unit tests.

describe("Expect", function(){   // Jasmine executes this function when the tests run
     describe("false", function(){
            it("to be equal to false", function(){  
                   expect(false).toEqual(false);    // expect function is the assert method
               });
       });

      // Add other describe functions here like the spyOn test below

});

Jasmine interprets this spec as "Expect false to be equal to false"  and give it this test name. The string "Expect" will be prepended to any tests within the group. The it function describes an actual test within the group. This function also takes 2 parameters just like the describe function.

We can also use the spyOn function to test(spy) if a function has been called, how many times it has been called and with what parameters.

     describe("my coolFunction", function(){
            
              it("is called", function(){
                 
                 // create object wrapper around the function expected to be called
                 var thisIs = {
                       coolFunction : function (){}
                 }

                 spyOn(thisIs, "coolFunction");


                  thisIs.coolFunction(); //call the function


                  expect(thisIs.coolFunction).toHaveBeenCalled();         

             });
         });
     });


Instead of calling the actual method, we should actually create and use a mock of the function as all we are interested in knowing is whether the function has been called or not.

Source Map in Browserify

While using Browserify to bundle all your JavaScript files into a single app.bundle.js file, come the time for debugging, it is very difficult to locate the exact source file where an exception occurred from the single giant file.

That's where a source map that you create (say during development) comes handy to quickly locate which source file is throwing the exception. The source map is just a mapping (dictionary) of the actual source files that helps us identify the source files without actually loading them in the browser.

To create a source map, you can issue the following command when you create the bundle from the command line, using --debug (shorthand is -d)

C:\Projects\MyApp> browserify src/js/app.js -o dist/js/app.bundle.js --debug

With Browserify, it creates this source map within the app.bundle.js file after encoding it as data-url (for the browser to recognize) it at the end of the file.

Since this increases the size of the file, it is recommended to turn it off before deploying to Production.

On the same note, to ease development so we don't have to manually run browserify every time a change is made, install watchify which is available as node package. This is just like brunch watch if using brunch to build your js files.

npm install -g watchify

So after installing it run this command just once with the -v option to watch verbosely

C:\Projects\MyApp> watchify src/js/app.js -o dist/js/app.bundle.js --debug -v


Now as your project and the build process gets more complicated, you might like to not only browserify and watchify your JavScript files, but use a build task runner like Gulp or Grunt. This is so you can lint your files, browserify it, mimimize it, add any less or sass files for styling etc. If using a task runner, you would have the task runner create a task to run browserify. We could still use watchify when using Grunt to automatically rebuild the files, but Grunt also comes with its own GruntWatch node module. This can be created as a grunt.loadNpmTasks()

Chrome won't give an option to clear the cache

While debugging an app on Chrome, discovered Chrome won't give any option to clear the cache. Even IE gives that option :-) but Google thinks it is the developer's problem of not clearing the cache and they won't support it. See this thread on Google code below. Seems to a lot of people that providing such an option may actually make Chrome look slower, so they aren't fixing it.

https://code.google.com/p/chromium/issues/detail?id=87604

Monday, May 25, 2015

MongoDB and .NET POCOs

While creating MongoDB documents, used nested objects and nested collections to take advantage of the way the POCO objects can be stored in the MongoDb documents doing away with the typical SQL impedance mismatch that ORMs try to solve.

By having nested objects within the same document, there are no need for JOINs and any constraints can live within the documents in a collection, just like relationships can exist between different tables in a relational database. That is feel free to use nested collections like arrays within your document or POCO object.

The MongoDB driver takes care of serializing your POCOs to MongoDB documents (internally stored as binary BSON documents in MongoDB) and deserializing them back to POCO objects without any noticebale friction, making programming very simple against MongoDB once the appropriate driver (mongo C# driver in our case) is installed in your project.

Avoid laying out your POCO objects based on your experience of creating POCO objects for SQL (multiple lean POCO entities with associations that turn into foreign key constraints). So stop replicating SQL in your POCO objects when working with MongoDB. So in MongoDB, take advantage of creating your rich domain models with nested objects, arrays and nested collections. Akin to pre-joining your SQL data across several tables out of the box!

So any data you typically work with at the same time, combine them into one single document for your document oriented design. The concept of an aggregate root in Domain Driven Design theory maps very nicely to Documents.

TIPS:

1) While declaring a decimal type field in your .NET POCO object, make sure you decorate it with the [BsonRepresenation(BsonType.Double)] attribute to convert it to the BSON double type. Otherwise the decimal CLR type is converted to string making any comparisons or indexing against the field string oriented and slow. Example, you want to sort and filter on a decimal Price field.

2) Also in the default serialization .NET characters and enums are represented as integers when a string may be desirable. So keep that in mind.

3) For DateTime, Mongo always uses UTC while .NET can use UTC as well as Local. This can have side-effects if we are not explicit about what date time type we want in our POCO object. So if using .NET Local time, always use the attribute [BsonDateTimeOptions(Kind = DateTimeKind=Local)]. Then when we deserialize the object back into .NET type using the BsonSerializer.Deserializer<T>, it will use the Local time zone correctly and not UTC.

4) Use DateOnly=true in your BsonDateTimeOptions if we want to ignore the time portion.

5) Use BsonIgnore attribute to ignore fields in the document

6) If you want to use a different field name rather than the default _id field, use BsonId attribute

7) At the class level, decorate with [BsonIgnoreExtraElements] if we want to remove fields from the document, without worrying with a file format exception that will be otherwise thrown by the Bson driver.





Sunday, May 24, 2015

Using Redis Client Code Snippets with ServiceStack

Code snippets in an MVC application:

using (IRedisClient redisClient = new RedisClient())
{      
      var userClient = new redisClient.GetTypedClient<User>();      
      var user = new User {                            
                                        Name = "Clint",                           
                                        Id = userClient.GetNextSequence()                     
      };               
      userClient.Store(user); // Save new User
}

On the redis-cli.exe command line, type monitor to see what's happening when you run the app.


MVC View to submit UserId from a dropdown selection to another Controller's action:

Select User:
@using (Html.BeginForm("Index", "Tracker", FormMethod.Post))
{     
    @DropDownList("userId", null, string.empty, new {@onchange = "form.submit();"});
}
@Html.ActionLink("Create New User", "NewUser", "Users");

Now with Redis, for Updates we don't really do an UPDATE like SQL. Instead we fetch the User, edit the data and RE-SAVE the User object.

And here's how you would associate a list of data with an User key-value pair. Create a set (list) which stores the UserId as a key value and a list of data (say integer values) for each Userid.

using (IRedisClient redisClient = new RedisClient())

      long userId = 213;
      int amount = 100;
    
      var userClient = new redisClient.GetTypedClient<User>();
      var user = userClient.GetById(userId);
  
      var historyClient = redisClient.GetTypedClient<int>();
      var historyList = historyClient.Lists["urn:history:" + userId];

      user.Total += amount;       
      userClient.Store(user); // Update User

      historyList.Prepend(amount); // always push to first item in the list
      historyList.Trim(0, 4); //restrict items in list to always 5 items

      /* Add to a sorted set that stores Users with key=name and value=total
         The beauty of Redis is it will not cause dups here and just updates the Total
         and maintains this sorted list! No code to write to check for dups etc.
     */
      redisClient.AddItemToSortedSet("urn:leaderboard", user.Name, user.Total);

      ViewBag.HistoryItems = historyList.GetAll();
}


//And to retrieve the leaderboard set, just call a method on the Redis client:
var leaderboard = redisClient.GetAllWithScoresFromSortedSet("urn:leaderboard");

Note; To avoid duplicates getting into the sorted set if we change the name of the User, make sure to remove the User from the sorted set whenever we "update", and then adding the User back again to the Sorted Set when we re-save the User. To remove the User from the sorted set, call redisClient.RemoveItemfromSortedSet("urn:leaderboard", user.Name).

And there you go! As simple as that.

TODO:

  • Add the ability to delete Users (slightly complicated as you need to keep track of where all your User data are)
  • Moving the history data to the User object rather than having it in its own list of integers
  • Store the User data in a hash. Is there any benefit to that?


Reference: Pluralsight training on Building NoSQL With Redis by John Sonmez
http://www.pluralsight.com/courses/building-nosql-apps-redis



Thursday, May 21, 2015

AngularJS Directive - Inherited Scope

Here's an example of a directive using inherited scope in AngularJS. See the plunk here:
http://plnkr.co/S8civ0l5KRL5cN2PBBJF

//index.html
<!DOCTYPE html>
<html ng-app="app">
  <head>
    <script data-require="jquery@2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js">           </script>
    <link data-require="bootstrap@*" data-semver="3.3.2" rel="stylesheet"     href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
    <script data-require="bootstrap@*" data-semver="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script data-require="angular.js@1.3.0" data-semver="1.3.0" src="https://code.angularjs.org/1.3.0/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>
  <body ng-controller="mainCtrl" class="container">
    <h5>
      <user-info-card user="user1"></user-info-card>
      <user-info-card user="user2"></user-info-card>
    </h5>
  </body>
</html>

/***************************************************************/
// script.js
angular.module('app',[]);
angular.module('app').controller('mainCtrl', function($scope){
  $scope.user1 = {
    name: "Luke Skywalker",
    address: {
      street: '6332 Cameron Forest Ln',
      city: "Charlotte",
      planet: "Earth"
    },
    friends: ['Han', 'Leia', 'Chewbacca']
  };

    $scope.user2 = {
    name: "Mia Farrow",
    address: {
      street: '1236 Cameron Forest Ln',
      city: "Charlotte",
      planet: "Vulcan"
    },
    friends: ['Lan', 'Tia', 'Chewbacca']
  };

  //console.log('parent scope', $scope);
  //Take this in the directive, so we don't break encapsulation and the directive handles this event
  /*
  $scope.knightMe = function(user){
    user.rank = "knight";
  }
  */
});
angular.module('app').directive('userInfoCard', function(){
  return {
    restrict: "E",
    templateUrl : "userInfoCard.html",
    replace: true, // will replace directive with the contents and not display the directive tag in the html element as best practice
    //scope: true, //inherited scope; false = shared scope with parent containing controller is the default
                 //scope: {}, would be isolated scope and the directive cannot see the controller's scope now
    scope: {
        user :"="
      }, //isolated scope but now controller(parent) scope user object can be shared by passing in
         // an user object user1 from the controller. Useful as the same directive can now be used across multiple controllers
         // and they can pass in thier scope user objects.
    controller: function($scope){
        $scope.collapsed = false; //parent variable
        $scope.knightMe = function(user){
              user.rank = "Knight";
         };
        $scope.collapse = function(){
          $scope.collapsed = !$scope.collapsed;
        }
    }
  }
});
//Put Address in its own directive so we can collapse it inside the panel-body of the useInfoCard directive.
//This will demonstrate inherited scope
angular.module('app').directive('address', function(){
  return {
    restrict: "E",
    scope: true,//THIS IS THE MAGIC ALLOWING Address to define its own collapsed variable, otherwise                     the variable is shared by default and clicking the address would close the entire panel-body
 
    templateUrl: "address.html",
    controller: function($scope){
   
      /* This statement below assigns another collapsed variable to address because of JavaScript's               prototypical inheritance.
         Otherwise, without this assignment statement that effectively creates(overrides) the collapsed variable for Address,
         it has the collapsed variable from the parent scope (userInfoCard directive in the html as address is nested inside that directive).
         Scope inheritance (setting scope: true in the child directive as above) thus propagates the scope from parent to child nested directive.
         In short, inheritance scope is very powerful as child directive can see properties in the parent scope, but be careful with it.
      */
      $scope.collapsed = false;
   
      $scope.collapseAddress = function(){
        $scope.collapsed = true;
      }
   
      $scope.expandAddress = function(){
        $scope.collapsed = false;
      }
    }
  }
})
                 // Note that we cannot make this isolated scope here because then user object in parent                                directive won't be accessible in the child directive

/*************************************************************************/

//userInfoCard.html parent directive
<div class="panel panel-primary">
  <!-- Have to wrap all elements within a root element for replace:true to work in  the directive -->
  <!-- The canonical Component directive. Almost always implemented as an element, defines a new widget-->
      <div class="panel-heading" ng-click="collapse()">{{user.name}} </div>
      <div class="panel-body" ng-hide="collapsed">
         <!--
         <h4>Address:</h4>
         <div ng-show='!!user.address' >
           {{user.address.street}}<br />
           City: {{user.address.city}}
         </div><br/>
        -->
        <!--Address is now in its own directive with inherited scope from userInfoCard directive-->
        <address></address>
     
        <h4>Friends:</h4>
        <ul>
          <li ng-repeat='friend in user.friends'>
            {{friend}}
          </li>
        </ul>
        <div ng-show="!!user.rank">
          <h4>Rank: {{user.rank}}</h4>
        </div><br/>
        <button class="btn-success" ng-click="knightMe(user)" ng-show="!user.rank">Knight Me</button>
      </div>
</div>


/**********************************************************************/

//address.html child directive that inherits scope

<div ng-show="!!user.address && !collapsed" ng-click="collapseAddress()">
   <h4>Address:</h4>
   <div ng-show='!!user.address' >
     {{user.address.street}}<br />
     City: {{user.address.city}}
   </div>
 </div>
 <div ng-show="!!user.address && collapsed" ng-click="expandAddress()">
   <h4>Address:</h4>
     {{user.address.street}}...
 </div>


AngularJS Directives - Isolated Scope

Here's an example for an Isolated Scope directive .  See the plunk here.  http://plnkr.co/lS8QIhaRbjqLlA7jHm2U

// Script.js
angular.module('app',[]);

angular.module('app').controller('mainCtrl', function($scope){
  $scope.user1 = {
    name: "Luke Skywalker",
    address: {
      street: '6332 Cameron Forest Ln',
      city: "Charlotte",
      planet: "Earth"
    },
    friends: ['Han', 'Leia', 'Chewbacca']
  };

    $scope.user2 = {
    name: "Mia Farrow",
    address: {
      street: '1236 Cameron Forest Ln',
      city: "Charlotte",
      planet: "Vulcan"
    },
    friends: ['Lan', 'Tia', 'Chewbacca']
  };

  //console.log('parent scope', $scope);
  //Take this in the directive, so we don't break encapsulation and the directive handles this event
  /*
  $scope.knightMe = function(user){
    user.rank = "knight";
  }
  */
});

/***************************************************************************/

//userCardInfo.html directive
angular.module('app').directive('userInfoCard', function(){
  return {
    restrict: "E",
    templateUrl : "userInfoCard.html",
    replace: true, // will replace directive with the contents and not display the directive tag in the html element as best practice
    //scope: true, //inherited scope; false = shared scope with parent containing controller is the default
                 //scope: {}, would be isolated scope and the directive cannot see the controller's scope now
    scope: {
        user :"="
      }, //isolated scope but now controller(parent) scope user object can be shared by passing in
         // an user object user1 from the controller. Useful as the same directive can now be used across multiple controllers
         // and they can pass in thier scope user objects.
    controller: function($scope){
        $scope.knightMe = function(user){
        user.rank = "Knight";
      }
    }
  }
})

/***************************************************************************/

//index.html
<!DOCTYPE html>
<html ng-app="app">

  <head>
      <script data-require="jquery@2.1.3" data-semver="2.1.4" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <link data-require="bootstrap@*" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
    <script data-require="bootstrap@*" data-semver="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script data-require="angular.js@1.3.0" data-semver="1.3.0" src="https://code.angularjs.org/1.3.0/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="mainCtrl" class="container">
    <h5>
       <user-info-card user="user1"></user-info-card>
       <user-info-card user="user2"></user-info-card>
    </h5>
 
  </body>

</html>

The core strength of Angular - Directives

Directives are JavaScript functions that allow you to manipulate the DOM or add behavior to it. That in a single sentence aptly describes what a Directive is in AngularJS.

Directives can be Angular predefined or custom directives. They can be very simple or extremely complicated. Getting a solid understanding of Directives is necessary to be a good Angular developer.

Each directive undergoes a "life cycle" as Angular compiles and links it to the DOM.
In a directive’s life cycle, there are four distinct functions that can execute if they are defined. Each enables the developer to control and customize the directive at different points of the life cycle. The four functions are

  • compile
  • controller
  • pre-link
  • post-link

The compile function allows the directive to manipulate the DOM before it is compiled and linked thereby allowing it to add/remove/change directives, as well as, add/remove/change other DOM elements.
The controller function facilitates directive communication. Sibling and child directives can request the controller of their siblings and parents to communicate information.
The pre-link function allows for private $scope manipulation before the post-link process begins.
The post-link method is the primary workhorse method of the directive.
Commonly the directive is defined as
  .directive("directiveName",function () {

    return {

      controller: function() {
        // controller code here...
      },
  
      link: function() {
        // post-link code here...
      }
    }
  })
The execution order of the functions within a directive and relative to other directives:
<div parentDir>
  <div childDir>
    <div grandChildDir>
    </div>
  </div>
</div>
The AngularJS directive function execution order relative to other directives.
Reference: http://www.toptal.com/angular-js/angular-js-demystifying-directives