First AngularJs example

If you are looking around for a new job as .NET developer, all companies are asking you AngularJs. Then I’m starting to learn it and I share with you the secret of this framework.

I’m assuming you are a .NET developer like me and you want to learn AngularJs and then I won’t explain you the basis of HTML.

Open Visual Studio and create a new solution with ASP.NET Empty web Site.

AnguarJS1-CreateEmptySolution-VisualStudio2017

Now you have your project.

AnguarJS1-EmptySolution-VisualStudio2017

Add from NuGet AngularJS.Core.

AnguarJS1-AddAngularJs-from-NuGet-VisualStudio2017

Done. We start now with a little complicate example. Two examples.

StartHere.html

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="Scripts/angular.min.js"></script>
</head>
<body ng-controller="ExampleController">
    <h1>Game setup</h1>
    <div ng-repeat="player in players" 
        ng-init="playerIndex = $index">
        <ng-include src="'player.html'"></ng-include>
    </div>
    <script>
        (function () {
            "use strict";
            var myAppModule = angular.module('myApp', []);

            myAppModule.factory('playerService', function () {
                var playerCount = 0;
                var createDefaultPlayer = function () {
                    playerCount += 1;
                    var player = {
                        name: "",
                        prevName: ""
                    };

                    player.onNameFocused = function () {
                        player.prevName = player.name;
                    };
                    return player;
                }

                return {
                    createPlayer: function (name) {
                        var player = createDefaultPlayer();
                        player.name = name;
                        return player;
                    },
                    getPlayerCount: function () {
                        return playerCount;
                    }
                };
            });

            myAppModule.controller('ExampleController', ['$scope', 'playerService',

                function ($scope, playerService) {

                    $scope.players = [playerService.createPlayer('Player1'),
                        playerService.createPlayer('Player2'),
                        playerService.createPlayer('Player3')];

                }

            ]);
        }());
    </script>
</body>
</html>

player.html

<h2>Player {{$playerIndex + 1}}</h2>
<label>Name:</label>
<input type="text" placeholder="Enter Player {{$playerIndex + 1}}" 
    ng-model="player.name" ng-focus="player.onNameFocused()" />
<h3 ng-show="player.name">
    Player {{$playerIndex + 1}} name is {{player.name}}
</h3>
<h3 ng-show="player.prevName">
    Prev Player {{$playerplayerIndex + 1}} name was 
    {{player.prevName}}
</h3>

Explanation

JavaScript frameworks such as Backbone.js, knockout.js, AngularJs and others addressed the problems of scalability, reusability, and testability by embracing a design pattern traditionally used by server-side frameworks.

This pattern is called Model-View-Controller (MVC), and it is an established pattern that was originally introduced in the 1970s. You should already be familiar with it from the ASP.NET MVC fundamentals, but I will revisit it here for reference.

Technically, AngularJS uses a variant of the MVC, which is closer to the Model-View-ViewModel (MVVM) pattern, but the definition of MVC from the next section still applies to it. One of the core members of the AngularJS team declared the main design pattern behind AngularJS as being "Model-View-Whatever works for you" (MVW or MV*) in this post at http://plus.google.com/+AngularJS/posts/aZNVhj355G2.

The design pattern is specific for applications with user interfaces and introduces a separation between the following aspects:

  • Model: This is the application data and the business logic associated with it

  • View: This is the output of the application data in any form that can be consumed or manipulated by a user

  • Controller: This is the logic to get data from the View to the Model and back, and to manage any interaction with the View or the Model

The first highlighted attribute is ng-app, which has a value this time around. The myApp value represents the unique identifier of the current AngularJS application. The next highlighted code initializes a new AngularJS component called module, which will be used via the myApp identifier to bootstrap the AngularJS application.

A module is a container-like object with a unique identifier that groups together the AngularJS components used to build an application: controllers, directives, and others, such as providers, factories, services, values, constants, animations, and filters. The module has methods that are specific to the AngularJS application components I mentioned.

The module controller function takes the controller name and controller constructor function as arguments.

The first highlighted snippet is the service definition that looks similar to a controller definition, with the exception that it returns an object that represents the service factory. This object is used to create the service instance that will be injected in all of the AngularJS components that have this service declared as a dependency.

In the new service, we transformed the previous controller code into a function called createDefaultPlayer(), which will create a new object that represents a player. The service instance has a method to create a new player with a predefined name called createPlayer(name). The service factory function will keep track of how many player objects were created using the playerCount variable. The variable will be returned by the service instance function, getPlayerCount(). On a side note, you can see the revealing module pattern in action here. Although the script section is now bigger, we obtained new features such as code reusability and flexibility to provide more complex functionality than before.

There are other methods available on the module interface to declare an AngularJS service, such as service, value, and constant. The service method will use a constructor function to create the service instance, while the value method will use an already created service instance that will be passed unchanged to the AngularJS injector. The constant method is similar with the value method, with the difference that it will be available during the configuration phase of the application module. The factory method is one of the most flexible methods, and it will be the most frequently used method in the rest of the examples from this book. It allows additional configuration to the returned service instance, and you can even keep track of data outside of the service instance, such as with the playerCount variable from the previous example.

We have used a lot of directives in the examples presented so far, and most of them used the ng- prefix. When you take a look at the directives' documentation pages at http://code.angularjs.org/1.2.15/docs/api, you will notice that the directive names appear slightly different—ng-app is ngApp and ng-controller is ngController. AngularJS removes any data- or x- prefixes from the HTML markup and converts the -, _, and : characters to a camel case directive name. From now on, we will refer to different directives using the names from the AngularJS documentation.

We will explore some important built-in directives and see how to build custom directives. Looking back at the previous example, the HTML markup seems to have been duplicated for the two players. There is a built-in directive called ngRepeat that allows us to remove the duplicated markup as highlighted in the next example.

The ngRepeat directive works with a collection of objects and repeats an HTML markup section for each item in the collection. We created an array of player items in the controller that is used in the ngRepeat directive. The first highlighted code section shows the expression used to iterate through the collection, and the div element that has the directive is repeated for each item in the collection. The player variable defined in the ngRepeat expression is only available inside of the directive. The ngRepeat directive has its own scope that contains other directive-specific variables such as $index, which has been used in the next highlighted code snippet. This variable of the type number keeps track of the current collection item index, and there are other directive-specific Boolean variables available: $first, $middle, $last, $odd, and $even.

The example works for HTML markup that repeats a single element. When the HTML markup that needs repeated elements has separate start and end elements, you need to use two different directive attributes. The first is ng-repeat-start, which is a renamed ng-repeat directive that needs to be used on the start HTML element. The second is ng-repeat-end, which does not have an expression value and is used on the HTML element that ends the markup that needs repeated elements. The previous example of the body element content can now be written using the h2 element as the start of the repeated markup and the h3 element as the end, as shown in the following code:

  <h1>Game setup</h1>
  <div>
    <h2 ng-repeat-start="player in players">
        Player {{$index + 1}}
    </h2>
    <label>Name:
    <input type="text" placeholder="Please enter player {{$index + 1}} name" 
        ng-model="player.name" ng-focus="player.onNameFocused()">
    <h3 ng-show="player.name">Player {{$index + 1}} name is {{player.name}}.</h3>
    <h3 ng-repeat-end ng-show="player.previousName">
        Previous Player {{$index + 1}} name was 
        {{player.previousName}}.
    </h3>
  </div>

The ngRepeat directive example is very useful when we need to manipulate the HTML for a specific application view. However, I can easily imagine scenarios where the HTML for a player has to be reused between different views. If there is a single player game, we want to see only one player editing form rather than two. AngularJS offers a simple but powerful solution through the ngInclude directive. This directive allows the referencing of a separate file that will be loaded and rendered in the current HTML view by AngularJS.

To introduce this directive, I had to change the HTML for the ngRepeat example and add a new file that contains the player HTML markup.

The first highlighted attribute is a new directive, ngInit, that evaluates an arbitrary expression. Although this directive can be used anywhere, it is best practice to only use it in the context of the ngRepeat directive. We use it to create a new scope property that is an alias of the $index variable from the ngRepeat directive. The reason behind this alias is to allow the reuse of the player markup in contexts where there is no enclosing ngRepeat directive.

The next highlighted element is the ngInclude directive, which fetches the referenced player.html file, renders it, and creates a new scope for it. The scope inherits the current ngRepeat iteration scope and its player and playerIndex properties. The last highlighted expression shows how the property created by ngInit is used in player markup.

Eat Cookies!

What are Cookies?

Cookies are data, stored in small text files, on your computer.

When a web server has sent a web page to a browser, the connection is shut down, and the server forgets everything about the user.

Cookies were invented to solve the problem "how to remember information about the user":

  • When a user visits a web page, his name can be stored in a cookie.
  • Next time the user visits the page, the cookie "remembers" his name.

Cookies are saved in name-value pairs like:

username = John Doe

When a browser requests a web page from a server, cookies belonging to the page is added to the request. This way the server gets the necessary data to "remember" information about users.

Function

function deleteCookie(cname) {
    setCookie(name, '', 1);
    document.cookie = name + '=; Expires=Thu, 01 Jan 1970 " + 
                      "00:00:01 GMT; path=/;';
}

function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) === 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
    var expires = "expires=" + d.toUTCString();
    document.cookie = cname + "=" + cvalue + "; " + expires + 
                      "; path=/;";
}

Happy coding!

Multi Step Form with Progress Bar using jQuery and CSS3

Wizard

Got long forms on your website ? Break them up into smaller logical sections and convert it into a multi-step form with a cool progress bar. Could work for lengthy processes like registration, checkout, profile fillups, 2-factor authentication logins, etc.

The form has 3 fieldsets containing the 3 different sections of the form. The fieldsets are absolutely positioned and only the first one is visible by default. Moving to the next section fades out the current fieldset using jQuery .animate() and brings in the next fieldset from the right. The reverse happens if the user moves to the previous section.

HTML

<!-- multistep form -->
<form id="msform">
	<!-- progressbar -->
	<ul id="progressbar">
		<li class="active">Account Setup</li>
		<li>Social Profiles</li>
		<li>Personal Details</li>
	</ul>
	<!-- fieldsets -->
	<fieldset>
		<h2 class="fs-title">Create your account</h2>
		<h3 class="fs-subtitle">This is step 1</h3>
		<input type="text" name="email" placeholder="Email" />
		<input type="password" name="pass" placeholder="Password" />
		<input type="password" name="cpass" placeholder="Confirm Password" />
		<input type="button" name="next" class="next action-button" value="Next" />
	</fieldset>
	<fieldset>
		<h2 class="fs-title">Social Profiles</h2>
		<h3 class="fs-subtitle">Your presence on the social network</h3>
		<input type="text" name="twitter" placeholder="Twitter" />
		<input type="text" name="facebook" placeholder="Facebook" />
		<input type="text" name="gplus" placeholder="Google Plus" />
		<input type="button" name="previous" class="previous action-button" value="Previous" />
		<input type="button" name="next" class="next action-button" value="Next" />
	</fieldset>
	<fieldset>
		<h2 class="fs-title">Personal Details</h2>
		<h3 class="fs-subtitle">We will never sell it</h3>
		<input type="text" name="fname" placeholder="First Name" />
		<input type="text" name="lname" placeholder="Last Name" />
		<input type="text" name="phone" placeholder="Phone" />
		<textarea name="address" placeholder="Address"></textarea>
		<input type="button" name="previous" class="previous action-button" value="Previous" />
		<input type="submit" name="submit" class="submit action-button" value="Submit" />
	</fieldset>
</form>

CSS

/*custom font*/
@import url(http://fonts.googleapis.com/css?family=Montserrat);

/*basic reset*/
* {margin: 0; padding: 0;}

html {
	height: 100%;
	/*Image only BG fallback*/
	background: url('http://thecodeplayer.com/uploads/media/gs.png');
	/*background = gradient + image pattern combo*/
	background: 
		linear-gradient(rgba(196, 102, 0, 0.2), rgba(155, 89, 182, 0.2)), 
		url('http://thecodeplayer.com/uploads/media/gs.png');
}

body {
	font-family: montserrat, arial, verdana;
}
/*form styles*/
#msform {
	width: 400px;
	margin: 50px auto;
	text-align: center;
	position: relative;
}
#msform fieldset {
	background: white;
	border: 0 none;
	border-radius: 3px;
	box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.4);
	padding: 20px 30px;
	
	box-sizing: border-box;
	width: 80%;
	margin: 0 10%;
	
	/*stacking fieldsets above each other*/
	position: absolute;
}
/*Hide all except first fieldset*/
#msform fieldset:not(:first-of-type) {
	display: none;
}
/*inputs*/
#msform input, #msform textarea {
	padding: 15px;
	border: 1px solid #ccc;
	border-radius: 3px;
	margin-bottom: 10px;
	width: 100%;
	box-sizing: border-box;
	font-family: montserrat;
	color: #2C3E50;
	font-size: 13px;
}
/*buttons*/
#msform .action-button {
	width: 100px;
	background: #27AE60;
	font-weight: bold;
	color: white;
	border: 0 none;
	border-radius: 1px;
	cursor: pointer;
	padding: 10px 5px;
	margin: 10px 5px;
}
#msform .action-button:hover, #msform .action-button:focus {
	box-shadow: 0 0 0 2px white, 0 0 0 3px #27AE60;
}
/*headings*/
.fs-title {
	font-size: 15px;
	text-transform: uppercase;
	color: #2C3E50;
	margin-bottom: 10px;
}
.fs-subtitle {
	font-weight: normal;
	font-size: 13px;
	color: #666;
	margin-bottom: 20px;
}
/*progressbar*/
#progressbar {
	margin-bottom: 30px;
	overflow: hidden;
	/*CSS counters to number the steps*/
	counter-reset: step;
}
#progressbar li {
	list-style-type: none;
	color: white;
	text-transform: uppercase;
	font-size: 9px;
	width: 33.33%;
	float: left;
	position: relative;
}
#progressbar li:before {
	content: counter(step);
	counter-increment: step;
	width: 20px;
	line-height: 20px;
	display: block;
	font-size: 10px;
	color: #333;
	background: white;
	border-radius: 3px;
	margin: 0 auto 5px auto;
}
/*progressbar connectors*/
#progressbar li:after {
	content: '';
	width: 100%;
	height: 2px;
	background: white;
	position: absolute;
	left: -50%;
	top: 9px;
	z-index: -1; /*put it behind the numbers*/
}
#progressbar li:first-child:after {
	/*connector not needed before the first step*/
	content: none; 
}
/*marking active/completed steps green*/
/*The number of the step and the connector before it = green*/
#progressbar li.active:before,  #progressbar li.active:after{
	background: #27AE60;
	color: white;
}

JavaScript

//jQuery time
var current_fs, next_fs, previous_fs; //fieldsets
var left, opacity, scale; //fieldset properties which we will animate
var animating; //flag to prevent quick multi-click glitches

$(".next").click(function(){
	if(animating) return false;
	animating = true;
	
	current_fs = $(this).parent();
	next_fs = $(this).parent().next();
	
	//activate next step on progressbar using the index of next_fs
	$("#progressbar li").eq($("fieldset").index(next_fs)).addClass("active");
	
	//show the next fieldset
	next_fs.show(); 
	//hide the current fieldset with style
	current_fs.animate({opacity: 0}, {
		step: function(now, mx) {
			//as the opacity of current_fs reduces to 0 - stored in "now"
			//1. scale current_fs down to 80%
			scale = 1 - (1 - now) * 0.2;
			//2. bring next_fs from the right(50%)
			left = (now * 50)+"%";
			//3. increase opacity of next_fs to 1 as it moves in
			opacity = 1 - now;
			current_fs.css({'transform': 'scale('+scale+')'});
			next_fs.css({'left': left, 'opacity': opacity});
		}, 
		duration: 800, 
		complete: function(){
			current_fs.hide();
			animating = false;
		}, 
		//this comes from the custom easing plugin
		easing: 'easeInOutBack'
	});
});

$(".previous").click(function(){
	if(animating) return false;
	animating = true;
	
	current_fs = $(this).parent();
	previous_fs = $(this).parent().prev();
	
	//de-activate current step on progressbar
	$("#progressbar li").eq($("fieldset").index(current_fs)).removeClass("active");
	
	//show the previous fieldset
	previous_fs.show(); 
	//hide the current fieldset with style
	current_fs.animate({opacity: 0}, {
		step: function(now, mx) {
			//as the opacity of current_fs reduces to 0 - stored in "now"
			//1. scale previous_fs from 80% to 100%
			scale = 0.8 + (1 - now) * 0.2;
			//2. take current_fs to the right(50%) - from 0%
			left = ((1-now) * 50)+"%";
			//3. increase opacity of previous_fs to 1 as it moves in
			opacity = 1 - now;
			current_fs.css({'left': left});
			previous_fs.css({'transform': 'scale('+scale+')', 'opacity': opacity});
		}, 
		duration: 800, 
		complete: function(){
			current_fs.hide();
			animating = false;
		}, 
		//this comes from the custom easing plugin
		easing: 'easeInOutBack'
	});
});

$(".submit").click(function(){
	return false;
})

 

Happy coding!

Start Edge Animate when is in the screen

I've come across a few sites that will tie window scrolling with animation. When used in a subtle, small fashion, this is kind of cool. When used to change large portions of the view or really screw with scrolling, I detect it. Like most things, it all comes down to how you use it I suppose. But I was thinking recently - how can we do this with Edge Animate?

Change edgePreload.js

In a file calles something_edgePreload.js you find a line similar to the follow:

    if (AdobeEdge.bootstrapLoading) { 
        signaledLoading = true; 
        AdobeEdge.loadResources = doLoadResources; 
        AdobeEdge.playWhenReady = playWhenReady; 
    }

Replace playWhenReady with false.

Change edgeActions.js

First of all you have to insert a function to decide if an element is in the visible part of the screen.

function isScrolledIntoView(elem) {
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) 
            && (elemTop >= docViewTop));
}

This function returns True if an element is in a visible portion of the screen.

Now we have to change the main function to check it and then play the animation. Here the complete code of an edgeAction.js.

(function($, Edge, compId){
var Composition = Edge.Composition, Symbol = Edge.Symbol; 
   // aliases for commonly used Edge classes

   //Edge symbol: 'stage'
   (function(symbolName) {
       var showAnimation = true;
       function isScrolledIntoView(elem) {
            var docViewTop = $(window).scrollTop();
            var docViewBottom = docViewTop + $(window).height();

            var elemTop = $(elem).offset().top;
            var elemBottom = elemTop + $(elem).height();

            return ((elemBottom <= docViewBottom) 
                    && (elemTop >= docViewTop));
      }

      Symbol.bindSymbolAction(compId, symbolName, 
                    "creationComplete", function(sym, e) {
          var animSize = sym.getDuration();

          if(!isScrolledIntoView('.EDGE-1931783')) {
	        setTimeout(function() { sym.stop(); }, 0);    
          }

           window.onscroll = function(e) {
              if(isScrolledIntoView('.EDGE-1931783')) {
                  if (showAnimation) {
                    sym.play(0);
                    showAnimation = false;
                  }
              }
          }
      });
   })("stage");
   //Edge symbol end:'stage'

})(jQuery, AdobeEdge, "EDGE-1931783");

EDGE-1931783 is the class of my animation. Replace it with yours.

Happy coding!

Integration with C# and ReactJS

The goal for this project is to show a list of books with ReactJS from a WebAPI written in C#. You can download this project from Github.

New project

Start by creating a new ASP.NET MVC 4 project: 1. File → New → Project 2. Select ".NET Framework 4" and Templates → Visual C# → Web → ASP.NET MVC 4 Web Application. Call it "CSReact" 3. In the "New ASP.NET MVC 5 (or 4) Project" dialog, select the MVC (or empty) template.

Install ReactJS.NET

We need to install ReactJS.NET to the newly-created project. This is accomplished using NuGet, a package manager for .NET. Right-click on the "ReactDemo" project in the Solution Explorer and select "Manage NuGet Packages". Search for "ReactJS.NET" and install the ReactJS.NET (MVC 4 and 5) package.

Create basic controller and view

Right-click on the Controllers folder and click Add → Controller. Name the controller "HomeController" and select "Empty MVC Controller" as the template. Once the controller has been created, right-click on return View() and click "Add View". Enter the following details:

  • View name: Index
  • View Engine: Razor (CSHTML)
  • Create a strongly-typed view: Unticked
  • Create as a partial view: Unticked
  • Use a layout or master page: Unticked

Replace the contents of the new view file with the following:

@{
    ViewBag.Title = "Home Page";
}
@section featured {
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1>@ViewBag.Title.</h1>
                <h2>@ViewBag.Message</h2>
            </hgroup>
            <p>
            </p>
        </div>
    </section>
}
<h3>React here:</h3>
<div id="content"></div>

@section scripts {
    <script src="https://fb.me/react-0.14.0.min.js"></script>
    <script src="https://fb.me/react-dom-0.14.0.min.js"></script>
    <script src="@Url.Content("~/Scripts/pages/books.jsx")"></script>
}

We also need to create the referenced JavaScript file books.jsx. Right-click on Scripts folder, select Add > New Folder, and enter "pages" as the folder name. Once created, right-click on the folder and select Add > New Item. Select Web > JavaScript File, enter "books.jsx" as the file name, and click "Add".

Create a model

Under Models folder add a new class called BookModels with the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace CSReact.Models {
   /// <summary>
   /// Book models
   /// </summary>
   public class BookModels {
      /// <summary>
      /// Title of the book
      /// </summary>
      public string Title { get; set; }

      /// <summary>
      /// Author of the book
      /// </summary>
      public string Author { get; set; }
   }
}

Generate WebAPI for Books

To generate a WebAPI right-click on Controllers folder and then you select Add → Controller. Choose now WebAPI 2 Controller - Empty and type Books. The API name will be BooksController.

Fill in the controller the following code:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http;
using System.Web.Script.Serialization;
using CSReact.Models;
using Newtonsoft.Json.Serialization;

namespace CSReact.Controllers
{
    public class BooksController : ApiController
    {
       public HttpResponseMessage Get() {
          IList<BookModels> result = new List<BookModels>();
          result.Add(new BookModels() { Author = "Michael Crichton", 
                                        Title = "Jurassic Park" });
          result.Add(new BookModels() { Author = "Agatha Christie", 
                                        Title = "And Then There Were None" });

          var formatter = new JsonMediaTypeFormatter();
          var json = formatter.SerializerSettings;

          json.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
          json.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
          json.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
          json.Formatting = Newtonsoft.Json.Formatting.Indented;
          json.ContractResolver = new CamelCasePropertyNamesContractResolver();
          json.Culture = new CultureInfo("en-GB");

          return Request.CreateResponse(HttpStatusCode.OK, result, formatter);
       }
    }
}

This API reply on your local server. You can call your API with an URL similar to

http://localhost:60273/api/books

and the result in the browser is a json result

[
  {
    "title": "Jurassic Park",
    "author": "Michael Crichton"
  },
  {
    "title": "And Then There Were None",
    "author": "Agatha Christie"
  }
]

Generate a book list

In the books.jsx file write the following code:

var BookList = React.createClass({
    render: function() {
        var bookNodes = this.props.data.map(function (book) {
            return (
                <div>
                    {book.title} ({book.author})
                </div>
            );
        });

        return (
            <div className="bookList">
                {bookNodes}
            </div>
        );
    }
});

This function will receive as a property data. data will contain the list of books that it has read from our WebAPI. For each row in data (you can read for each book in data), it creates a new div with title and author from book. The function returns a new div within the list of book.

Then we can write the other part of the books.jsx where you read the data from the WebAPI and display it calling BookList function. The complete code of books.jsx is

var BookList = React.createClass({
    render: function() {
        var bookNodes = this.props.data.map(function (book) {
            return (
                <div>
                    {book.title} ({book.author})
                </div>
            );
        });

        return (
            <div className="bookList">
                {bookNodes}
            </div>
        );
    }
});

var App = React.createClass({
    getInitialState: function() {
        return {data: []};
    },

    componentDidMount: function() {
        $.get(this.props.url, function(result) {
            var book = result[0];
            if (this.isMounted()) {
            }
        }.bind(this));
    },

    componentWillMount: function() {
        var xhr = new XMLHttpRequest();
        xhr.open('get', this.props.url, true);
        xhr.onload = function() {
            var jdata = JSON.parse(xhr.responseText);
            this.setState({ data: jdata });
        }.bind(this);
        xhr.send();
    },

    render: function() {
        return (
          <div className="commentBox">
            <BookList data={this.state.data} />
          </div>
      )
    }
});

ReactDOM.render(
  <App url="/api/books/Get" />,
  document.getElementById('content')
);

If you're lucky and try to start your app, you can see the list of books in your index page.

ReactJS: component Lifecycle and Rendering

These are the functions that will be, or can be, included in your specification object when you’re creating a component. Part of these specification functions are lifecycle functions, which when encountered, will show the details as to when they execute during the life of a component.

Function invocation order during the initial render of a React component

Function_invocation_order_during_the_initial_render_of_a_React_component

Component lifecycle that happens when the state changes on a component

Component_lifecycle_that_happens_when_the_state_changes_on_a_component

Lifecycle of a component when it has altered props

Lifecycle_of_a_component_when_it_has_altered_props

render

Every React component must have a render function. This render function will accept a ReactElement and provide a container location where the component will be added or mounted to the DOM.

getInitialState

This function will return an object. The contents of this object will set the state of the component when it initially renders. This function is invoked one time, just before the component renders. When creating a component using ES6 classes, you will actually be setting the state, via this.state, within the constructor function of the class.

getDefaultProps

When a ReactClass is first created, getDefaultProps is invoked one time and then is cached. This function returns an object that will represent the default state of this.props on the component. Values for this.props that do not exist in the parent component, but are present in the component’s mapping, will be added to this.props here. When you’re creating a component using the ES6 setting, the default props is done within the constructor function of your component class.

Mixins

A mixin in the component specification is an array. A mixin can share the lifecycle events of your component and you can be assured that the functionality will execute during the proper time during the component’s lifecycle. An example mixin is a timer control that merges the lifecycle events of a SetIntervalMixin with the main component called TickTock.

Example of Mixin in jsfiddle

displayName

displayName is a property that is used when you see debugging messages from your React app.

componentWillMount

componentWillMount is a lifecycle event that React uses during the process of taking your component class and rendering it to your DOM. The componentWillMount method is executed once before the initial render of your component. The unique thing about componentWillMount is that if you call your setState function within this function, it will not cause a re-render of your component because the initial render method will receive the modified state.

componentWillMount()

componentDidMount

componentDidMount is a function that’s invoked only on the client side of React processing, after the component has been rendered to the DOM. At this point, the React component has become a part of the DOM and you can access it using the React.findDOMNode function.

componentDidMount()

componentWillReceiveProps

componentWillReceiveProps is executed when the component will be receiving props. This function is invoked every time that there is a prop change, but never on the first render. You can call setState inside this function and you will not cause an additional render. The function that you provide will have an argument for the next props object that is going to become part of the component’s props. Within this function though you still have access to the current props using this.props so you can make any logic comparisons between this.props and nextProps in this function.

componentWillReceiveProps( nextProps )

shouldComponentUpdate

This function is invoked before a component renders and each time a change in prop or state is received. It will not be called before the initial render, or when forceUpdate is utilized. This function is a mechanism that you can use to skip rendering if you know that the changes to the props or state will not actually require the component to update. To short-circuit the render process, you need to return false in the function body, based on whatever criteria you determine. Doing this will bypass the rendering of the component, by not only skipping the render() function but also the next steps in the lifecycle — componentWillUpdate and componentDidUpdate

shouldComponentUpdate( nextProps, nextState );

componentWillUpdate

componentWillUpdate is invoked right before a render occurs on your component. You cannot use setState in this function.

componentWillUpdate( nextProps, nextState )

componentDidUpdate

componentDidUpdate is executed just after all the rendering updates are processed into the DOM. Since this is based on an update, it is not part of the initial render of the component. The arguments available to this function are the previous props and previous state.

componentDidUpdate( prevProps, prevState );

componentWillUnmount

When a component is rendered to the DOM, it is called mounting. It follows then that this function componentWillUnmount would be invoked immediately before the component is no longer going to be mounted to the DOM.

componentWillUnmount()

Advertsing

125X125_06