Friday, July 29, 2016

A Step-by-Step Tutorial for Your First AngularJS App

What is AngularJS?

AngularJS is a JavaScript MVC framework developed by Google that lets you build well structured, easily testable, and maintainable front-end applications.

And Why Should I Use It?

If you haven’t tried AngularJS yet, you’re missing out. The framework consists of a tightly integrated toolset that will help you build well structured, rich client-side applications in a modular fashion—with less code and more flexibility.
AngularJS extends HTML by providing directives that add functionality to your markup and allow you to create powerful dynamic templates. You can also create your own directives, crafting reusable components that fill your needs and abstracting away all the DOM manipulation logic.
It also implements two-way data binding, connecting your HTML (views) to your JavaScript objects (models) seamlessly. In simple terms, this means that any update on your model will be immediately reflected in your view without the need for any DOM manipulation or event handling (e.g., with jQuery).
Angular provides services on top of XHR that dramatically simplify your code and allow you to abstract API calls into reusable services. With that, you can move your model and business logic to the front-end and build back-end agnostic web apps.

We at Oye Trade are conducting AngularJs Training in Delhi NCR, please visit www.oyetrade.com to book your seat.
Finally, I love Angular because of its flexibility regarding server communication. Like most JavaScript MVC frameworks, it lets you work with any server-side technology as long as it can serve your app through a RESTful web API. But Angular also provides services on top of XHR that dramatically simplify your code and allow you to abstract API calls into reusable services. As a result, you can move your model and business logic to the front-end and build back-end agnostic web apps. In this post, we’ll do just that, one step at a time.

So, Where Do I Begin?

First, let’s decide the nature of the app we want to build. In this guide, we’d prefer not to spend too much time on the back-end, so we’ll write something based on data that’s easily attainable on the Internet—like a sports feed app!
Since I happen to be a huge fan of motor racing and Formula 1, I’ll use an autosport API service to act as our back-end. Luckily, the guys at Ergast are kind enough to provide a free motorsport API that will be perfect for us.
For a sneak peak at what we’re going to build, take a look at the live demo. To prettify the demo and show off some Angular templating, I applied a Bootstrap theme from WrapBootstrap, but seeing as this article isn’t about CSS, I’ll just abstract it away from the examples and leave it out.

Getting Started Tutorial

Let’s kickstart our example app with some boilerplate. I recommend the angular-seed project as it not only provides you with a great skeleton for bootstrapping, but also sets the ground for unit testing with Karma andJasmine (we won’t be doing any testing in this demo, so we’ll just leave that stuff aside for now; see Part 2 of this tutorial for more info on setting up your project for unit and end-to-end testing).
EDIT (May 2014): Since I wrote this tutorial, the angular-seed project has gone through some heavy changes (including the additon of Bower as package manager). If you have any doubts about how to deploy the project, take a quick look at the first section of their reference guide. In Part 2 of ths tutorial, Bower, among other tools, is covered in greater detail.
OK, now that we’ve cloned the repository and installed the dependencies, our app’s skeleton will look like this:
angularjs tutorial - start with the skeleton
Now we can start coding. As we’re trying to build a sports feed for a racing championship, let’s begin with the most relevant view: the championship table.
the championship table
Given that we already have a drivers list defined within our scope (hang with me – we’ll get there), and ignoring any CSS (for readability), our HTML might look like:
<body ng-app="F1FeederApp" ng-controller="driversController">
  <table>
    <thead>
      <tr><th colspan="4">Drivers Championship Standings</th></tr>
    </thead>
    <tbody>
      <tr ng-repeat="driver in driversList">
        <td>{{$index + 1}}</td>
        <td>
          <img src="img/flags/{{driver.Driver.nationality}}.png" />
          {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}}
        </td>
        <td>{{driver.Constructors[0].name}}</td>
        <td>{{driver.points}}</td>
      </tr>
    </tbody>
  </table>
</body>
The first thing you’ll notice in this template is the use of expressions (“{{“ and “}}”) to return variable values. In AngularJS, expressions allow you to execute some computation in order to return a desired value. Some valid expressions would be:
  • {{ 1 + 1 }}
  • {{ 946757880 | date }}
  • {{ user.name }}
Effectively, expressions are JavaScript-like snippets. But despite being very powerful, you shouldn’t use expressions to implement any higher-level logic. For that, we use directives.

Understanding Basic Directives

The second thing you’ll notice is the presence of ng-attributes, which you wouldn’t see in typical markup. Those are directives.
At a high level, directives are markers (such as attributes, tags, and class names) that tell AngularJS to attach a given behaviour to a DOM element (or transform it, replace it, etc.). Let’s take a look at the ones we’ve seen already:
  • The ng-app directive is responsible for bootstrapping your app defining its scope. In AngularJS, you can have multiple apps within the same page, so this directive defines where each distinct app starts and ends.
  • The ng-controller directive defines which controller will be in charge of your view. In this case, we denote the driversController, which will provide our list of drivers (driversList).
  • The ng-repeat directive is one of the most commonly used and serves to define your template scope when looping through collections. In the example above, it replicates a line in the table for each driver in driversList.

Adding Controllers

Of course, there’s no use for our view without a controller. Let’s add driversController to our controllers.js:
angular.module('F1FeederApp.controllers', []).
controller('driversController', function($scope) {
    $scope.driversList = [
      {
          Driver: {
              givenName: 'Sebastian',
              familyName: 'Vettel'
          },
          points: 322,
          nationality: "German",
          Constructors: [
              {name: "Red Bull"}
          ]
      },
      {
          Driver: {
          givenName: 'Fernando',
              familyName: 'Alonso'
          },
          points: 207,
          nationality: "Spanish",
          Constructors: [
              {name: "Ferrari"}
          ]
      }
    ];
});
You may have noticed the $scope variable we’re passing as a parameter to the controller. The $scopevariable is supposed to link your controller and views. In particular, it holds all the data that will be used within your template. Anything you add to it (like the driversList in the above example) will be directly accessible in your views. For now, let’s just work with a dummy (static) data array, which we will replace later with our API service.
Now, add this to app.js:
angular.module('F1FeederApp', [
  'F1FeederApp.controllers'
]);
With this line of code, we actually initialize our app and register the modules on which it depends. We’ll come back to that file (app.js) later on.
Now, let’s put everything together in index.html:
<!DOCTYPE html>
<html>
<head>
  <title>F-1 Feeder</title>
</head>

<body ng-app="F1FeederApp" ng-controller="driversController">
  <table>
    <thead>
      <tr><th colspan="4">Drivers Championship Standings</th></tr>
    </thead>
    <tbody>
      <tr ng-repeat="driver in driversList">
        <td>{{$index + 1}}</td>
        <td>
          <img src="img/flags/{{driver.Driver.nationality}}.png" />
          {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}}
        </td>
        <td>{{driver.Constructors[0].name}}</td>
        <td>{{driver.points}}</td>
      </tr>
    </tbody>
  </table>
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="js/app.js"></script>
  <script src="js/services.js"></script>
  <script src="js/controllers.js"></script>
</body>
</html>
Modulo minor mistakes, you can now boot up your app and check your (static) list of drivers.
Note: If you need help debugging your app and visualizing your models and scope within the browser, I recommend taking a look at the awesome Batarang plugin for Chrome.

Loading Data From the Server

Since we already know how to display our controller’s data in our view, it’s time to actually fetch live data from a RESTful server.
To facilitate communication with HTTP servers, AngularJS provides the $http and $resource services. The former is but a layer on top of XMLHttpRequest or JSONP, while the latter provides a higher level of abstraction. We’ll use $http.
To abstract our server API calls from the controller, let’s create our own custom service which will fetch our data and act as a wrapper around $http by adding this to our services.js:
angular.module('F1FeederApp.services', []).
  factory('ergastAPIservice', function($http) {

    var ergastAPI = {};

    ergastAPI.getDrivers = function() {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK'
      });
    }

    return ergastAPI;
  });
With the first two lines, we create a new module (F1FeederApp.services) and register a service within that module (ergastAPIservice). Notice that we pass $http as a parameter to that service. This tells Angular’s dependency injection engine that our new service requires (or depends on) the $http service.
In a similar fashion, we need to tell Angular to include our new module into our app. Let’s register it with app.js, replacing our existing code with:
angular.module('F1FeederApp', [
  'F1FeederApp.controllers',
  'F1FeederApp.services'
]);
Now, all we need to do is tweak our controller.js a bit, include ergastAPIservice as a dependency, and we’ll be good to go:
angular.module('F1FeederApp.controllers', []).
  controller('driversController', function($scope, ergastAPIservice) {
    $scope.nameFilter = null;
    $scope.driversList = [];

    ergastAPIservice.getDrivers().success(function (response) {
        //Dig into the responde to get the relevant data
        $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
    });
  });
Now reload the app and check out the result. Notice that we didn’t make any changes to our template, but we added a nameFilter variable to our scope. Let’s put that variable to use.

Filters

Great! We have a functional controller. But it only shows a list of drivers. Let’s add some functionality by implementing a simple text search input which will filter our list. Let’s add the following line to our index.html, right below the <body> tag:
<input type="text" ng-model="nameFilter" placeholder="Search..."/>
We are now making use of the ng-model directive. This directive binds our text field to the $scope.nameFiltervariable and makes sure that its value is always up-to-date with the input value. Now, let’s visit index.html one more time and make a small adjustment to the line that contains the ng-repeat directive:
<tr ng-repeat="driver in driversList | filter: nameFilter">
This line tells ng-repeat that, before outputting the data, the driversList array must be filtered by the value stored in nameFilter.
At this point, two-way data binding kicks in: every time a value is input in the search field, Angular immediately ensures that the $scope.nameFilter that we associated with it is updated with the new value. Since the binding works both ways, the moment the nameFilter value is updated, the second directive associated to it (i.e., the ng-repeat) also gets the new value and the view is updated immediately.
Reload the app and check out the search bar.
app search bar
Notice that this filter will look for the keyword on all attributes of the model, including the ones we´re not using. Let’s say we only want to filter by Driver.givenName and Driver.familyName: First, we add to driversController, right below the $scope.driversList = []; line:
$scope.searchFilter = function (driver) {
    var keyword = new RegExp($scope.nameFilter, 'i');
    return !$scope.nameFilter || keyword.test(driver.Driver.givenName) || keyword.test(driver.Driver.familyName);
};
Now, back to index.html, we update the line that contains the ng-repeat directive:
<tr ng-repeat="driver in driversList | filter: searchFilter">
Reload the app one more time and now we have a search by name.

Routes

Our next goal is to create a driver details page which will let us click on each driver and see his/her career details.
First, let’s include the $routeProvider service (in app.js) which will help us deal with these varied application routes. Then, we’ll add two such routes: one for the championship table and another for the driver details. Here’s our new app.js:
angular.module('F1FeederApp', [
  'F1FeederApp.services',
  'F1FeederApp.controllers',
  'ngRoute'
]).
config(['$routeProvider', function($routeProvider) {
  $routeProvider.
 when("/drivers", {templateUrl: "partials/drivers.html", controller: "driversController"}).
 when("/drivers/:id", {templateUrl: "partials/driver.html", controller: "driverController"}).
 otherwise({redirectTo: '/drivers'});
}]);
With that change, navigating to http://domain/#/drivers will load the driversController and look for the partial view to render in partials/drivers.html. But wait! We don’t have any partial views yet, right? We’ll need to create those too.

Partial Views

AngularJS will allow you to bind your routes to specific controllers and views.
But first, we need to tell Angular where to render these partial views. For that, we’ll use the ng-view directive, modifying our index.html to mirror the following:
<!DOCTYPE html>
<html>
<head>
  <title>F-1 Feeder</title>
</head>

<body ng-app="F1FeederApp">
  <ng-view></ng-view>
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="js/app.js"></script>
  <script src="js/services.js"></script>
  <script src="js/controllers.js"></script>
</body>
</html>
Now, whenever we navigate through our app routes, Angular will load the associated view and render it in place of the <ng-view> tag. All we need to do is create a file named partials/drivers.html and put our championship table HTML there. We’ll also use this chance to link the driver name to our driver details route:
<input type="text" ng-model="nameFilter" placeholder="Search..."/>
<table>
<thead>
  <tr><th colspan="4">Drivers Championship Standings</th></tr>
</thead>
<tbody>
  <tr ng-repeat="driver in driversList | filter: searchFilter">
    <td>{{$index + 1}}</td>
    <td>
      <img src="img/flags/{{driver.Driver.nationality}}.png" />
      <a href="#/drivers/{{driver.Driver.driverId}}">
    {{driver.Driver.givenName}}&nbsp;{{driver.Driver.familyName}}
   </a>
 </td>
    <td>{{driver.Constructors[0].name}}</td>
    <td>{{driver.points}}</td>
  </tr>
</tbody>
</table>
Finally, let’s decide what we want to show in the details page. How about a summary of all the relevant facts about the driver (e.g., birth, nationality) along with a table containing his/her recent results? To do that, we add to services.js:
angular.module('F1FeederApp.services', [])
  .factory('ergastAPIservice', function($http) {

    var ergastAPI = {};

    ergastAPI.getDrivers = function() {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK'
      });
    }

    ergastAPI.getDriverDetails = function(id) {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/driverStandings.json?callback=JSON_CALLBACK'
      });
    }

    ergastAPI.getDriverRaces = function(id) {
      return $http({
        method: 'JSONP', 
        url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/results.json?callback=JSON_CALLBACK'
      });
    }

    return ergastAPI;
  });
This time, we provide the driver’s ID to the service so that we retrieve the information relevant solely to a specific driver. Now, we modify controllers.js:
angular.module('F1FeederApp.controllers', []).

  /* Drivers controller */
  controller('driversController', function($scope, ergastAPIservice) {
    $scope.nameFilter = null;
    $scope.driversList = [];
    $scope.searchFilter = function (driver) {
        var re = new RegExp($scope.nameFilter, 'i');
        return !$scope.nameFilter || re.test(driver.Driver.givenName) || re.test(driver.Driver.familyName);
    };

    ergastAPIservice.getDrivers().success(function (response) {
        //Digging into the response to get the relevant data
        $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
    });
  }).

  /* Driver controller */
  controller('driverController', function($scope, $routeParams, ergastAPIservice) {
    $scope.id = $routeParams.id;
    $scope.races = [];
    $scope.driver = null;

    ergastAPIservice.getDriverDetails($scope.id).success(function (response) {
        $scope.driver = response.MRData.StandingsTable.StandingsLists[0].DriverStandings[0]; 
    });

    ergastAPIservice.getDriverRaces($scope.id).success(function (response) {
        $scope.races = response.MRData.RaceTable.Races; 
    }); 
  });
The important thing to notice here is that we just injected the $routeParams service into the driver controller. This service will allow us to access our URL parameters (for the :id, in this case) using $routeParams.id.
Now that we have our data in the scope, we only need the remaining partial view. Let’s create a file named partials/driver.html and add:
<section id="main">
  <a href="./#/drivers"><- Back to drivers list</a>
  <nav id="secondary" class="main-nav">
    <div class="driver-picture">
      <div class="avatar">
        <img ng-show="driver" src="img/drivers/{{driver.Driver.driverId}}.png" />
        <img ng-show="driver" src="img/flags/{{driver.Driver.nationality}}.png" /><br/>
        {{driver.Driver.givenName}} {{driver.Driver.familyName}}
      </div>
    </div>
    <div class="driver-status">
      Country: {{driver.Driver.nationality}}   <br/>
      Team: {{driver.Constructors[0].name}}<br/>
      Birth: {{driver.Driver.dateOfBirth}}<br/>
      <a href="{{driver.Driver.url}}" target="_blank">Biography</a>
    </div>
  </nav>

  <div class="main-content">
    <table class="result-table">
      <thead>
        <tr><th colspan="5">Formula 1 2013 Results</th></tr>
      </thead>
      <tbody>
        <tr>
          <td>Round</td> <td>Grand Prix</td> <td>Team</td> <td>Grid</td> <td>Race</td>
        </tr>
        <tr ng-repeat="race in races">
          <td>{{race.round}}</td>
          <td><img  src="img/flags/{{race.Circuit.Location.country}}.png" />{{race.raceName}}</td>
          <td>{{race.Results[0].Constructor.name}}</td>
          <td>{{race.Results[0].grid}}</td>
          <td>{{race.Results[0].position}}</td>
        </tr>
      </tbody>
    </table>
  </div>

</section>
Notice that we’re now putting the ng-show directive to good use. This directive will only show the HTML element if the expression provided is true (i.e., neither false, nor null). In this case, the avatar will only show up once the driver object has been loaded into the scope by the controller.

Finishing Touches

Add in a bunch of CSS and render your page. You should end up with something like this:
page rendered with CSS
You’re now ready to fire up your app and make sure both routes are working as desired. You could also add a static menu to index.html to improve the user’s navigation capabilities. The possibilities are endless.
EDIT (May 2014): I’ve received many requests for a downloadable version of the code that we build in this tutorial. I’ve therefore decided to release it here (stripped of any CSS). However, I really do not recommend downloading it, since this guide contains every single step you need to build the same application with your own hands, which will be a much more useful and effective learning exercise.

Conclusion

At this point in the tutorial, we’ve covered everything you’d need to write a simple app (like a Formula 1 feeder). Each of the remaining pages in the live demo (e.g., constructor championship table, team details, calendar) share the same basic structure and concepts that we’ve reviewed here.
Finally, keep in mind that Angular is a very powerful framework and we’ve barely scratched the surface in terms of everything it has to offer. In Part 2 of this tutorial, we’ll give examples of why Angular stands out among its peer front-end MVC frameworks: testability. We’ll review the process of writing and running unit tests with Karma, achieving continuous integration with YeomenGrunt, and Bower, and other strengths of this fantastic front-end framework.
This article was written by Raoni Boaventura, a Toptal Javascript developer.

We at Oye Trade are conducting AngularJs Training in Delhi NCR, please visit www.oyetrade.com to book your seat.

Thursday, July 21, 2016

The 5 Most Common Mistakes HTML5 Developers Make: A Beginner’s Guide

It’s been over 20 years since Tim Berners-Lee and Robert Cailliau specified HTML, which became the standard markup language used to build the Internet. Ever since then, the HTML development community has begged for improvements to this language, but this cry was mostly heard by web browser developers who tried to ease the HTML issues of their colleagues. Unfortunately, this led to even more problems causing many cross-browser compatibility issues and duplication of development work. Over these 20 years, HTML was upgraded 4 times, while most of the browsers got double-digit numbers of major updates plus numerous small patches.
HTML5 was supposed to finally solve our problems and become one standard to rule them all (browsers). This was probably one of the most anticipated technologies since creation of the World Wide Web. Has it happened? Did we finally get one markup language that will be fully cross-browser compatible and will work on all desktop and mobile platforms giving us all of those features we were asking for? I dont know! Just few days ago (Sept. 16th 2014) we received one more call for review by W3C so the HTML5 specification is still incomplete.
Despite HTML5 issues and mistakes, is it the one language ring to rule them all?
Hopefully, when the specification is one day finalized, browsers will not already have significant obsolete code, and they will easily and properly implement great features like Web WorkersMultiple synchronized audio and video elements, and other HTML5 components that we’ve needed for a long time.
Give hasty developers an incomplete spec, and you'll have a recipe for disaster.
We do however have thousands of companies that have based their businesses on HTML5 and are doing great. There are also many great HTML5-based applications and games used by millions of people, so success is obviously possible and HTML5 is, and will continue to be, used regardless on the status of its specification.
However, the recipe I mentioned can easily blow up in our faces, and thus I’ve emphasized some of the most basic HTML5 mistakes that can be avoided. Most of the mistakes listed below are consequence of incomplete or missing implementation of certain HTML5 elements in different browsers, and we should hope that in the near future they will become obsolete. Until this happens, I suggest reading the list and having it in mind when building your next HTML5 application whether you’re an HTML5 beginner or an experienced vet.

Common mistake #1: Trusting local storage

Let them eat cake! This approach has been a burden on developers for ages. Due to reasonably sensible fear of security breaches and protection of computers, in the “dark ages” when the Internet was feared by many, web applications were allowed to leave unreasonably small amounts of data on computers. True, there were things like user data that “great browser masters from Microsoft(r)” gave us, or things like Local Shared Objects in Flash, but this was far from perfect.
It is therefore reasonable that one of the first basic HTML5 features adopted by developers was Web Storage. However, be alert that Web Storage is not secure. It is better than using cookies because it will not be transmitted over the wire, but it is not encrypted. You should definitely never store security tokens there. Your security policy should never rely on data stored in Web Storage as a malicious user can easily modify her localStorage and sessionStorage values at any time.
To get more insight on Web Storage and how to use it, I suggest reading this post.

Common mistake #2: Expecting compatibility among browsers

HTML5 is much more than a simple markup language. It has matured enough to combine behavior together with layout, and you should consider HTML5 as extended HTML with advanced JavaScript on top. If you look at all the trouble we had before just to make a static combination of HTML+CSS look identical on all browsers, it is fair to assume that more complexity will just mean more effort assuring cross-browser compatibility.
HTML5 interpretation on different browsers is far from identical, just like the case was with JavaScript. All major players in the browser wars lended a hand in the HTML5 spec, so it’s fair to assume that deviations between browsers should reduce over time. But even now some browsers decided to fully ignore certain HTML5 elements making it very difficult to follow a baseline and common set of features. If we add more internet connected devices and platforms to the equation, the situation gets even more complicated, causing problems with HTML5.
For example Web Animations are great feature that is supported only by Chrome and Opera, while Web Notification feature that allows alerting the user outside the context of a web page of an occurrence, such as the delivery of email, is fully ignored by Internet Explorer.
To learn more about HTML5 features and support by different browsers check out the HTML5 guide at www.caniuse.com.
So the fact remains that even though HTML5 is new and well specified, we should expect a great deal of cross-browser compatibility issues and plan for them in advance. There are just too many gaps that browsers need to fill in, and it is fair to expect that they cannot overcome all of the differences between platforms well.

Common mistake #3: Assuming high performance

Regardless of the fact that HTML5 is still evolving, it is a very powerful technology that has many advantages over alternate platforms used before its existence. But, with great power comes great responsibility, especially for HTML5 beginners. HTML5 has been adopted by all major browsers on desktop and mobile platforms. Having this in mind, many development teams pick HTML5 as their preferred platform, hoping that their applications will run equally on all browsers. However, assuming sensible performance on both desktop and mobile platforms just because HTML5 specification says so, is not sensible. Lots of companies (khm! Facebook khm!) placed their bets on HTML5 for their mobile platform and suffered from HTML5 not working out as they planned.
Again, however, there are some great companies that rely heavily on HTML5. Just look at the numerous online game development studios that are doing amazing stuff while pushing HTML5 and browsers to their limits. Obviously, as long as you are aware of the performance issues and are working around these, you can be in a great place making amazing applications.

Common mistake #4: Limited accessibility

Web has become a very important part of our lives. Making applications accessible to people who rely upon assistive technology is important topic that is often put aside in software development. HTML5 tries to overcome this by implementing some of the advanced accessibility features. More than a few developers accepted this to be sufficient and haven’t really spent any time implementing additional accessibility options in their applications. Unfortunately, at this stage HTML5 has issues that prevent it from making your applications available to everyone and you should expect to invest additional time if you want to include a broader range of users.
You can check this place for more information about accessibility in HTML5 and the current state of the most common accessibility features.

Common mistake #5: Not using HTML5 enhancements

HTML5 has extended the standard HTML/XHTML set of tags significantly. In addition to new tags, we got quite a few new rules and behaviors. Too many developers picked up just a few enhancements and have skipped some of the very cool new features of HTML5.
One of the coolest things in HTML5 is client-side validation. This feature was probably one of the earliest elements of HTML5 that web browsers picked up. But, unfortunately, you can find more than a few developers who add novalidate attribute to their forms by default. The reasons for doing this arereasonable, and I’m quite sure we will have a debate about this one. Due to backward compatibility, many applications implemented custom JavaScript validators and having out-of-the-box validation done by browsers on top of that is inconvenient. However, it is not too difficult to assure that two validation methods will not collide, and standardizing user validation will ensure common experience while helping to resolve accessibility issues that I mentioned earlier.
Another great feature is related to the way user input is handled in HTML5. Before HTML5 came, we had to keep all of our form fields contained inside the <form></form> tag. New form attributes make it perfectly valid to do something like this:
<form action="demo_form.asp" id="form1">
  First name: <input type="text" name="fname"><br>
  <input type="submit" value="Submit">
</form>

Last name: <input type="text" name="lname" form="form1">
Even if lname is not inside the form, it will be posted together with fname.
For more information about new form attributes and enhancements, you can check the Mozilla Developer Network.

Wrap up

I understand that web developers are collateral damage in the browser wars as many of the above mistakes are a direct consequence of problematic HTML5 implementation in different browsers. However, it is still crucial that we avoid common HTML5 issues and spend some time understanding the new features of HTML5. Once we have it all under control, our applications will utilize great new enhancements and take the web to the next level.
This post originally appeared in the Toptal Engineering blog