Implementing Responsive web design with Angular Material UI is very easy. It is having predefined directives for different views (mobile, tablet, desktop). You need to understand them and use them in proper way.

Directives for showing elements

Observe the below table. These directives implements "display:block" CSS property based on width of device

show-smShows element on devices less than 600px wide.
show-gt-smShows element on devices greater than 600px wide.
show-mdShows element on devices between 600px and 960px wide.
show-gt-mdShows element on devices greater than 960px wide.
show-lgShows element on devices between 960px and 1200px wide.
show-gt-lgShows element on devices greater than 1200px wide.

Directives for hiding elements

Observe the below table. These directives implements "display:none" CSS property based on width of device.
hide-smhide element on devices less than 600px wide.
hide-gt-smhide element on devices greater than 600px wide.
hide-mdhide element on devices between 600px and 960px wide.
hide-gt-mdhide element on devices greater than 960px wide.
hide-lghide element on devices between 960px and 1200px wide.
hide-gt-lghide element on devices greater than 1200px wide.

Directives for setting width of elements

Observe the below table. These directives implements "width: %" CSS property based on width of device.The value must be 33,66,99 or multiples of 5 (5, 15, 30, 50...)
flexwidth percentage of element
flex-smwidth percentage of element on devices less than 600px wide.
flex-gt-smwidth percentage of element on devices greater than 600px wide.
flex-mdwidth percentage of element on devices between 600px and 960px wide.
flex-gt-mdwidth percentage of element on devices greater than 960px wide.
flex-lgwidth percentage of element on devices between 960px and 1200px wide.
flex-gt-lgwidth percentage of element on devices greater than 1200px wide.

Views 

Desktop

Here we have to hide mobile and tablet views and show the desktop view
hide-md hide-sm show-gt-md

Tablet

Here we have to hide desktop and mobile views and show the tablet view 
hide-gt-md hide-sm show-md

Mobile 

Here we have to hide desktop and tablet views and show the mobile view
hide-gt-sm show-sm

Example 1: Create Responsive Header

Observe below diagram. Desktop and Tablet and Mobile are having different views. Lets implement this with above directives.

HTML Code 

Observe below highlighted code. 

<md-toolbar>
      <div class="md-toolbar-tools" ng-hide="showSearchBarDiv">
        <md-button class="md-icon-button" aria-label="Icon">
          <md-tooltip>Icon</md-tooltip>
          <md-icon class="md-default-theme" md-svg-icon="fb.svg"></md-icon>
        </md-button>
        <h2>
          <span>Heading</span>
        </h2>
        <md-input-container md-no-float class="md-accent" flex="50" style="padding-bottom:0px;margin-left:25px" show-gt-md hide-sm hide-md>
           <md-icon style="color:wheat" class="material-icons">&#xE8B6;</md-icon>
           <input ng-model="searchInput" placeholder="Search here" style="color:wheat;padding-left:25px;margin-left:5px">
        </md-input-container>
        <span flex></span>
        <md-button class="md-icon-button" hide-gt-md show-sm show-md ng-click="showSearchBarDiv = true">
          <md-tooltip>Search</md-tooltip>
          <img src="search.png" style="width:24px;height:24px;"/>
        </md-button>
        <md-button class="md-icon-button" show-gt-sm hide-sm>
          <md-tooltip>Pen</md-tooltip>
          <img src="pen.png" style="width:24px;height:24px;"/>
        </md-button>
        <md-button class="md-icon-button" show-gt-sm hide-sm>
          <md-tooltip>Messages</md-tooltip>
          <img src="messages.png" style="width:24px;height:24px;"/>
        </md-button>
        <md-button class="md-icon-button" show-gt-sm hide-sm>
          <md-tooltip>User</md-tooltip>
          <img src="user.png" style="width:24px;height:24px;"/>
        </md-button>
        <md-button class="md-icon-button" show-gt-sm hide-sm>
          <md-tooltip>Settings</md-tooltip>
          <img src="settings.png" style="width:24px;height:24px;"/>
        </md-button>
        <md-button class="md-icon-button" hide-gt-sm show-sm>
          <md-tooltip>Menu</md-tooltip>
          <img src="menu.png" style="width:24px;height:24px;"/>
        </md-button>
      </div>
      <div layout="row" class="md-toolbar-tools" show-sm show-md hide-gt-md ng-show="showSearchBarDiv">
        <md-button class="md-icon-button" ng-click="showSearchBarDiv = false">
          <img src="back.png" style="width:24px;height:24px;"/>
        </md-button>
        <md-input-container flex="80" md-no-float class="md-accent" style="padding-bottom:0px;">
           <md-icon style="color:wheat" class="material-icons">&#xE8B6;</md-icon>
           <input ng-model="searchInput" placeholder="Search here" style="color:wheat;padding-left:25px;margin-left:5px">
        </md-input-container>
        <span flex></span>
        <md-button class="md-icon-button">
          <img src="search.png" style="width:24px;height:24px;"/>
        </md-button>
      </div>
</md-toolbar>

Example 2: Create Responsive Body

 Observe below diagram. There are 3 panels (Left side, news feed, right side). In desktop view, all 3 panels are visible. In tablet view, only left panel and news feed are visible. In mobile view, Only news feed is visible.

HTML Code

Observe below highlighted code. Here we are also using flex directive. Flex value specified based on the view
<div layout="row">
       <div class="panel" flex="20" flex-md="30" show-gt-sm hide-sm>Left Side Panel</div>
       <div class="panel" flex="60" flex-sm="100" flex-md="70">News Feed</div>
       <div class="panel" flex="20" show-gt-md hide-sm hide-md>Right Side Panel</div>
</div>
Read More
First see Grid list in AngularJS Material UI, There is no documentation over grid list directives. I didn't understand anything because of not having proper documentation. After reading whole material UI documentation, I just tried examples and understood the concept of grid-list.

Grid-list directives


md-colsSets Number of columns
md-cols-smSets Number of columns on devices less than 600px wide.
md-cols-gt-smSets Number of columns on devices greater than 600px wide.
md-cols-mdSets Number of columns on devices between 600px and 960px wide.
md-cols-gt-mdSets Number of columns on devices greater than 960px wide.
md-cols-lgSets Number of columns on devices between 960px and 1200px wide.
md-cols-gt-lgSets Number of columns on devices greater than 1200px wide.

md-row-heightSets row height ratio
md-row-height-smSets row height ratio on devices less than 600px wide.
md-row-height-gt-smSets row height ratio on devices greater than 600px wide.
md-row-height-mdSets row height ratio on devices between 600px and 960px wide.
md-row-height-gt-mdSets row height ratio on devices greater than 960px wide.
md-row-height-lgSets row height ratio on devices between 960px and 1200px wide.
md-row-height-gt-lgSets row height ratio on devices greater than 1200px wide.

md-gutterSets Margin to grid
md-gutter-smSets Margin to grid on devices less than 600px wide.
md-gutter-gt-smSets Margin to grid on devices greater than 600px wide.
md-gutter-mdSets Margin to grid on devices between 600px and 960px wide.
md-gutter-gt-mdSets Margin to grid on devices greater than 960px wide.
md-gutter-lgSets Margin to grid on devices between 960px and 1200px wide.
md-gutter-gt-lgSets Margin to grid on devices greater than 1200px wide.

md-colspanSets column size to grid
md-colspan-smSets column size to grid on devices less than 600px wide.
md-colspan-gt-smSets column size to grid on devices greater than 600px wide.
md-colspan-mdSets column size to grid on devices between 600px and 960px wide.
md-colspan-gt-mdSets column size to grid on devices greater than 960px wide.
md-colspan-lgSets column size to grid on devices between 960px and 1200px wide.
md-colspan-gt-lgSets column size to grid on devices greater than 1200px wide.

md-rowspanSets row size to grid
md-rowspan-smSets row size to grid on devices less than 600px wide.
md-rowspan-gt-smSets row size to grid on devices greater than 600px wide.
md-rowspan-mdSets row size to grid on devices between 600px and 960px wide.
md-rowspan-gt-mdSets row size to grid on devices greater than 960px wide.
md-rowspan-lgSets row size to grid on devices between 960px and 1200px wide.
md-rowspan-gt-lgSets row size to grid on devices greater than 1200px wide.

md-cols Example

This directive is for setting the number of columns in grid system. Observe below highlighted code.    For mobile devices, l column will be there. For tablets 2 columns will be there. For desktops 3 columns will be there.
<md-grid-list md-cols-gt-md="3" md-cols-md="2" md-cols-sm="1" md-gutter="12px" md-row-height="1:1">
    <md-grid-tile class="green">
      <md-grid-tile-footer>
        <h3>first tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="blue">
      <md-grid-tile-footer>
        <h3>second tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="purple">
      <md-grid-tile-footer>
        <h3>third tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
 </md-grid-list>

md-colspan Example

Here colspan is for setting width of the tile. Here I have given different sizes for below tiles for mobile, tablet, desktop
<md-grid-list md-cols-gt-md="9" md-cols-md="6" md-cols-sm="3" md-gutter="12px" md-row-height="1:1">
    <md-grid-tile class="green" md-colspan-gt-md="6" md-colspan-md="4" md-colspan-sm="1">
      <md-grid-tile-footer>
        <h3>first tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="blue" md-colspan-gt-md="2" md-colspan-md="1" md-colspan-sm="1">
      <md-grid-tile-footer>
        <h3>second tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="purple" md-colspan-gt-md="1" md-colspan-md="1" md-colspan-sm="1">
      <md-grid-tile-footer>
        <h3>third tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
</md-grid-list>

md-rowspan Example

Here rowspan is for setting height of the tile. Here I have given different sizes for below tiles for mobile, tablet, desktop
<md-grid-list md-cols="9" md-gutter="12px" md-row-height="1:1">
    <md-grid-tile class="green" md-rowspan-gt-md="3" md-rowspan-md="2" md-rowspan-sm="2">
      <md-grid-tile-footer>
        <h3>first tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="blue" md-rowspan-gt-md="2" md-rowspan-md="3" md-rowspan-sm="1">
      <md-grid-tile-footer>
        <h3>second tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="purple" md-rowspan-gt-md="1" md-rowspan-md="1" md-rowspan-sm="3">
      <md-grid-tile-footer>
        <h3>third tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
</md-grid-list>

md-gutter Example

This is for setting margin for grids. Here you can observe different margins for mobile, tablet, desktop views
<md-grid-list md-cols="3" md-gutter-gt-md="60px" md-gutter-md="30px" md-gutter-sm="2px" md-row-height="1:1">
    <md-grid-tile class="green">
      <md-grid-tile-footer>
        <h3>first tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="blue">
      <md-grid-tile-footer>
        <h3>second tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="purple">
      <md-grid-tile-footer>
        <h3>third tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
</md-grid-list>

md-row-height Example

This is the ratio of grid width and grid height. Here you can observe different ratios for mobile, tablet, desktop views
<md-grid-list md-cols="6" md-gutter="12px" md-row-height-gt-md="3:1" md-row-height-md="1:3" md-row-height-sm="1:1">
    <md-grid-tile class="green">
      <md-grid-tile-footer>
        <h3>first tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="blue">
      <md-grid-tile-footer>
        <h3>second tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
    <md-grid-tile class="purple">
      <md-grid-tile-footer>
        <h3>third tile</h3>
      </md-grid-tile-footer>
    </md-grid-tile>
</md-grid-list>
Read More
If you search something in google, you can see that sentence in your next search as a suggestion. We don't need the server side coding to implement this functionality. We can save all those searching key words in HTML5 local storage and show them in next's user search. Here I have implemented this functionality with AngularJS Material UI.

Program Flow

Observe the below diagram for program flow. Whenever user clicks on submit button, add search text to local storage. Whenever user changes the search text, show filtered key words from local storage in auto complete manner 

Markup Code

Here I have highlighted the main code components
  1. searchByEnter will detect user's actions of typing including enter code functionality
  2. searchText is the value of user's input
  3. querySearch(searchText) will return all filtered results
  4. addSearchQueryTORepo is for adding searchText to local storage
<md-autocomplete ng-keyup="searchByEnter($event)" ng-disabled="isDisabled" md-no-cache="noCache" md-selected-item="selectedItem" md-search-text-change="searchTextChange(searchText)" md-search-text="searchText" md-selected-item-change="selectedItemChange(item)" md-items="item in querySearch(searchText)" md-item-text="item" md-min-length="0" placeholder="Enter Some text and click on sumbit">
     <md-item-template>
        <span md-highlight-text="searchText" md-highlight-flags="^i">{{item}}</span>
     </md-item-template>
     <md-not-found>
        No matches found for "{{searchText}}".
     </md-not-found>
 </md-autocomplete>
<md-button class="md-raised md-primary" ng-click="addSearchQueryTORepo()">Submit</md-button>

JS Code

Observe below code. Here I have highlighted HTML5 local storage related code.
app.controller('AppCtrl', function($scope) {
    
   $scope.searchByEnter = function($event) {  
     if($event.keyCode == 13) {
       $scope.addSearchQueryTORepo();
       var myEl = angular.element($event.target);
       myEl.blur();
     }
   };
   
   $scope.addSearchQueryTORepo = function() {
     var lowCaseSearchStr = $scope.searchText.toLowerCase();
     var searchQueries = localStorage.getItem("searchQueries");
     var sQrs = [];
     if(searchQueries != null) {
        sQrs = JSON.parse(searchQueries);
        var sind = sQrs.indexOf(lowCaseSearchStr);
        if(sind != -1) {
          sQrs.splice(sind,1);  
        }
          sQrs.splice(0,0,lowCaseSearchStr);
          localStorage.setItem("searchQueries", JSON.stringify(sQrs));
        } else {
          sQrs.splice(0,0,lowCaseSearchStr);
          localStorage.setItem("searchQueries", JSON.stringify(sQrs));
      }
   };
   
   $scope.querySearch = function(query) {
     var st = localStorage.getItem("searchQueries");
     if(st!=null) {
         var states = JSON.parse(st);
         $scope.localStrResults = states;
         var searchResults = [];
         var myQuery = query.toLowerCase();
         for(var i=0;i<states.length;i++) {
           if(states[i].toLowerCase().indexOf(myQuery) != -1) {
             searchResults.push(states[i]);
           }
         }
         return searchResults;   
     }
   };
});
Read More
Recently I have created form validations for Change Password functionality.  This form will have 4 important fields ( User-id, Old-password, New-password, Confirm-password). Here Old-password should not equal to New-password and New-password should be equal to Confirm-password. Now here we need two directives. One directive is matching Old-password with New-password and another is for matching New-password with Confirm password. In this article, I have implemented the example with AngulaJS material UI.

Directives 

Here in below code, you can find two directives. unMatcher returns true, If 2 input fields are not equal. matcher returns true, If 2 input fields are equal 
app.directive("unMatcher", function($timeout) {
        return {
            restrict : "A",

            require : "ngModel",

            link : function(scope, element, attributes, ngModel) {
                ngModel.$validators.unMatcher = function(modelValue) {
                    return attributes.unMatcher !== modelValue;
                };
            }
        };
    });

app.directive("matcher", function($timeout) {
        return {
            restrict : "A",

            require : "ngModel",

            link : function(scope, element, attributes, ngModel) {
                ngModel.$validators.matcher = function(modelValue) {
                    return attributes.matcher === modelValue;
                };
            }
        };
    });

Change Password Form Validation

Now I am going to implement change password form field validation here. Find highlighted part of  below code.  
<div ng-controller="AppCtrl" class="header" ng-app="MyApp"
    style="margin: auto; width: 800px">
    <form name="userForm">
        <md-input-container flex> 
          <label>Old Password</label> 
          <input type="password" name="oldPassword" ng-model="oldPassword" required>
          <div ng-messages="userForm.oldPassword.$error">
              <div ng-message="required">This is required.</div>
           </div>
        </md-input-container>
        <md-input-container flex> 
          <label>New Password</label> 
          <input type="password" name="newPassword" ng-model="newPassword" required un-matcher="{{oldPassword}}">
          <div ng-messages="userForm.newPassword.$error">
              <div ng-message="required">This is required.</div>
              <div ng-message="unMatcher">New Password cannot be same as Old Password.</div>
           </div>
        </md-input-container>
        <md-input-container flex> 
          <label>Confirm Password</label> 
          <input type="password" name="confirmPassword" ng-model="confirmPassword" required matcher="{{oldPassword}}">
          <div ng-messages="userForm.confirmPassword.$error">
              <div ng-message="required">This is required.</div>
              <div ng-message="matcher">Confirm Password should be same as old Password.</div>
           </div>
        </md-input-container>
        <md-button class="md-raised md-primary" ng-disabled="userForm.$invalid">Sumbit</md-button>
    </form>
</div>

Whole JS code

Here ngMaterial is for handling material directives and ngMessages is showing error messages
var app = angular.module('MyApp', [ 'ngMaterial', 'ngMessages' ]);

    app.controller('AppCtrl', function($scope) {
       $scope.oldPassword = '';
       $scope.newPassword = '';
       $scope.confirmPassword = '';
    });

    app.directive("unMatcher", function($timeout) {
        return {
            restrict : "A",

            require : "ngModel",

            link : function(scope, element, attributes, ngModel) {
                ngModel.$validators.unMatcher = function(modelValue) {
                    return attributes.unMatcher !== modelValue;
                };
            }
        };
    });

    app.directive("matcher", function($timeout) {
        return {
            restrict : "A",

            require : "ngModel",

            link : function(scope, element, attributes, ngModel) {
                ngModel.$validators.matcher = function(modelValue) {
                    return attributes.matcher === modelValue;
                };
            }
        };
    });
Read More

Blogroll


Follow this blog by Email

Popular Posts