Showing posts with label Angular. Show all posts
Showing posts with label Angular. Show all posts

Saturday, June 23, 2018

Declare Date/DateTime pipes globally to use in application wide

In my previous articles, I have written how to create custom date/datetime formatting pipes use in your application. As a practice, I think it will be good if you can include similar pipes like these into a module where you can use in the application rather importing all the pipes separately into the app.module.ts.
Rather than using these two pipes separately, let's create a module and declare and export in a global level. So that it can be used in throughout the application. I'm going to use exactly same code which I wrote in above two articles.

Step 01: Create an Angular App
  $ ng new demoPipeApp

Step 02: Navigate to your dateFormatApp
  $ cd demoPipeApp

Step 03: Create a file to store format options

constants.ts
export class Constants {
    public static readonly dateFormat: string = "dd-MM-yyyy";
    public static readonly dateTimeFormat: string = `${Constants.dateFormat} HH:mm`;
}

Step 04: Create a Module to register all the pipes using Angular CLI
  $ ng g module DateTimeFormatPipes


  // this will creatte date-format-pipes.module.ts

Step 05: Create "DateTimeFormat" Pipe using Angular CLI
  $ ng g pipe DateTimeFormat

date-time-format.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common';

@Pipe({
  name: 'dateTimeFormat'
})
export class DateTimeFormatPipe extends DatePipe implements PipeTransform {

  transform(value: any, args?: any): any {
    return super.transform(value, this.dateTimeFormat);
  }
}

Step 06: Create "DateFormat" Pipe using Angular CLI
  $ ng g pipe DateFormat

date-format.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common';
import { Constants } from '../modals/constants';

@Pipe({
  name: 'dateFormat'
})
export class DateFormatPipe extends DatePipe implements PipeTransform {

  transform(value: any, args?: any): any {
    return super.transform(value, Constants.dateFormat);
  }
}

Step 07: Declare and Export both pipes in "date-format-pipes.module.ts"


date-format.pipe.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DateFormatPipe } from './date-format.pipe';
import { DateTimeFormatPipe } from './date-time-format.pipe';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [DateFormatPipe, DateTimeFormatPipe],
  exports: [DateFormatPipe, DateTimeFormatPipe]
})
export class DateFormatPipesModule { }

Step 08: Import "DateFormatPipesModule" to "app.module.ts" 
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { DateFormatPipesModule } from './date-format-pipes/date-format-pipes.module';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, DateFormatPipesModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


Step 09: Modify the "app.component.html"
Date: {{date | dateFormat}}
DateTime: {{date | dateTimeFormat}}

Output

Format DateTime with a Custom DateTime Pipe in Angular 2 +

I have explained creating a custom date formatting in angular 2 using pipes in my previous article. In this article, I'm going to create an application with custom DateTime Pipe which can configure the format from one place that will affect to the entire application without find and replace the hard-coded angular default formatting options.

Step 01: Create an Angular App
  $ ng new dateTimeFormatApp

Step 02: Navigate to your dateFormatApp
  $ cd dateTimeFormatApp

Step 03: Create a Pipe using Angular CLI
  $ ng g pipe DateTimeFormat

date-time-format.pipe.ts looks like this:
import { Pipe, PipeTransform } from '@angular/core';
import { DateTimePipe } from '@angular/common';

@Pipe({
  name: 'dateTimeFormat'
})
export class DateFormatPipe extends DatePipe implements PipeTransform {

  private readonly dateTimeFormat = "dd-MM-yyyy HH:mm"; // feel free to move this to a constants.ts file
  transform(value: any, args?: any): any {
    return super.transform(value, this.dateTimeFormat);
  }
}
app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Custome DateTimeFormat Pipe Demo';
  date = new Date();
}
app.component.html
Welcome to {{ title }}!
Date: {{date | dateTimeFormat}}

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { DateTimeFormatPipe } from './pipes/date-time-format.pipe';

@NgModule({
  declarations: [AppComponent, DateTimeFormatPipe],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Output

Format Dates with a Custom Date Pipe in Angular 2 +

Angular 2 DatePipe provides different sets of formats to display in a browser. Angular DatePipe comes with @angular/common. The date input can be given as date object, milliseconds or an ISO date string.

DatePipe is a Pipe API that works using pipe operator ( | ). Accordingly, you can place date expression on the left side of the pipe, and on the right side with required date formats based on as
{{ value_expression | date [ : format [ : timezone [ : locale ] ] ] }}
given in the official documentation.

By default, most of the predefined formats support the American date format (month/day/year). But, If you like to go with default formatting as giving in the documentation, you can use

Date : {{currentDate | date }}

Date : {{currentDate | date: 'MMM-dd-yyyy' }}

Date : {{currentDate | date: 'MM-dd-yyyy' }}

Date : {{currentDate | date: 'yMMMdjms' }}

Date : {{currentDate | date: 'yMMMMEEEEd' }}

As a good programming practice, it is always recommended to
wrap default pipe in your application. Assume, you have defined the date to be displayed as 'short' with default formatting throughout the application which angular has provided.

In case if the client asks to update the date format throughout the application the only way is to find and replace date format in the entire application which is not going to be a scalable solution in long-term.

Let's create a custom dateFormat pipe to cater this issue to configure your dateFormat in a single place.

Step 01: Create an Angular App
  $ ng new dateFormatApp

Step 02: Navigate to your dateFormatApp
  $ cd dateFormatApp

Step 03: Create a Pipe using Angular CLI
  $ ng g pipe DateFormat

So, date-format.pipe.ts looks like this:
import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common';

@Pipe({
  name: 'dateFormat'
})
export class DateFormatPipe extends DatePipe implements PipeTransform {

  private readonly dateFormat = "dd-MM-yyyy"; // feel free to move this to a constants.ts file
  transform(value: any, args?: any): any {
    return super.transform(value, this.dateFormat);
  }
}
app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Custome DateFormat Pipe Demo';
  date = new Date();
}
app.component.html
Welcome to {{ title }}!
Date: {{date | dateFormat}}

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { DateFormatPipe } from './pipes/date-format.pipe';

@NgModule({
  declarations: [AppComponent, DateFormatPipe],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Output


Tuesday, May 22, 2018

What is new in Angular 6.0

AngularJS is a JavaScript-based open-source front-end web application framework maintained by Google, which combines declarative templates, dependency injection, end-to-end tooling, and integrated best practices to solve development challenges.

In addition, Angular JavaScript components complement Apache Cordova, a framework used for developing cross-platform mobile apps. Google released the initial version on October 20, 2010, and the latest stable version released on last May 11, 2018. Angular 2.0 was a complete re-write of the initial AngularJs version 1.0 entirely based on components.

The most importantly, this release makes Angular lighter, faster and easier. Moreover, it will make developers life easier on upcoming Angular versions. As you many know Angular 6 is already out there as a preview version, let’s find out upcoming features and enhancements.

In March 2016, the initial version of Angular Material was released but was lacking in the number of components, stability, and compatibility with latest angular versions. The latest release on angular 6.0, now it has become more stable and compatible. The ultimate goal of this package is to create an Angular component and publish it as a Web Component, which can be used in any HTML page that is being supported by all modern browsers (Except Edge). The main benefit of this is, once you create and publish a web component, you can and use it in a non-SPA app.

With this release, CDK Toolkit is stable and Developers can use this toolkit to build their own components using Angular Material which is also supported Responsive Web Design layouts eliminating the need for using libraries like Flex Layout or learning CSS Grid with less effort as this toolkit already has most of the commonly used utilities to build components.

Angular CLI generates Angular artifacts using the technology called Schematics that enables developers to create a new component, or updating the code to fix breaking changes in a dependency or to add a new configuration option or new framework to an existing project. By using “ng update” it automatically updates the project dependencies and makes automated version fixes by itself.

Service worker is a script that runs in the web browser and manages to cache for an application. In the older version, when we do the latest deployment of the application it may need to deactivate/uninstall the existing service worker. With this new release, it contains new script file safety-worker.js, which will be a part of production bundle that helps us to unregister existing service worker.

It is common that introducing new functionality/features to the application gradually increases the size of the application bundle size. App Budgets is a handy feature in the Angular CLI, which allows developers to set thresholds values for the size of bundles that will enable to configure error messages/warning messages when bundle size grows beyond the configured threshold.

The Angular team has introduced a new backward-compatible renderer, Ivy Renderer which will make the size of the app smaller and the compilation faster. Switching to Ivy rendered will be smooth, and the Angular team has promised it will be a non-breaking change for existing implementations.

This new release of the Angular version with TypeScript 2.7+ will be much easier to code with conditional type declarations, default declarations and strict class initialization. Please refer this link to read the full spec of latest additions to TypeScript version.

In Angular old versions, there is no direct way of knowing if navigation was triggered imperatively or via the location change. In latest Angular version, it has introduced “navigationSource” to identify the source of the navigation. Moreover, the “restoredState” will give the restored navigation id, which leads to current navigation. These two properties are useful to handle multiple use cases in routing.

As you know, when we introduce a service or annotated a class with @Injectable, we have to register in app module under providers section. With the new changes in Angular 6, you can specify “providedIn” and it will auto-register itself when the app bootstraps by simplifying  dependency injection.

Most of software built by Google, including over 300+ Angular apps were built by using Bazel build system. Since the source code changes often, it does not make sense to rebuild the entire application for every little change instead Bazel only rebuilds what is necessary. The Closure Compiler is capable of consistently generates smaller bundles and does a better job in dead code elimination compared to Webpack and Rollup bundlers.

Friday, October 21, 2016

Read and Write permission for storage and gallery - open failed: EACCES (Permission denied) Cordova

After Android OS upgrade to Marshmallow(6.0), permission has categorized into two sections "Normal and Dangerous Permissions". On this version on wards, users have to grant permission when the app is running but not at the time of app installation via play store. Also app developers have to request permission on "Dangerous Permission" at the time of using device resources such as Camera, Location, Gallery, External Storage.

Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically.

Dangerous permissions can give the app access to the user's confidential data. If your app lists a normal permission in its manifest, the system grants the permission automatically. If you list a dangerous permission, the user has to explicitly give approval to your app.
(Reference: Android API)


Let's create a sample Ionic project using Visual Studio 2015 to see how it is get done beginning of Marshmallow(API Level 23).

Step 01:- Create a Iconic tab template

Step 02:- Install File, FileTransfer, Permission plugins

cordova plugin add cordova-plugin-file
cordova plugin add cordova-plugin-file-transfer
cordova plugin add cordova-plugin-android-permissions@0.10.0

Please refer more details for the API urls listed below:

  • file (https://github.com/apache/cordova-plugin-file)
  • file-transfer (https://github.com/apache/cordova-plugin-file-transfer)
  • permissions (https://github.com/NeoLSN/cordova-plugin-android-permission)
Step 03:- Add a button to your UI and create a method in your control.

angular.module('starter.controllers', ['ionic'])

.controller('DashCtrl', function ($scope, $ionicPlatform) {

    $scope.downloadFile = function () {

        $ionicPlatform.ready(function () {
       // File for download
       var url = "http://www.gajotres.net/wp-content/uploads/2015/04/logo_radni.png";

       // File name only
       var filename = url.split("/").pop();

       // Save location
        var targetPath = cordova.file.externalRootDirectory + 'Download/' + filename;

       var fileTransfer = new FileTransfer();
       var uri = encodeURI(url);
       var trustHosts = true
       var options = {};


            fileTransfer.download(
                uri,
                targetPath,
                function (entry) {
                    console.log("download complete: " + entry.toURL());
                },
                function (error) {
                    console.log("download error source " + error.source);
                    console.log("download error target " + error.target);
                    console.log("download error code" + error.code);
                },
                trustHosts,
                options
            );
        });
    };
})

If you run this code without requesting permission for external storage, it will throw  open failed: EACCES (Permission denied) error message.

Step 04:-  Let's modify the code to request permission for storage.

Note: Go through the API documentation for more details.

//var permissions = cordova.plugins.permissions;
//permissions.hasPermission(permission, successCallback, errorCallback);
//permissions.requestPermission(permission, successCallback, errorCallback);
//permissions.requestPermissions(permissions, successCallback, errorCallback);


var permissions = cordova.plugins.permissions;
permissions.hasPermission(permissions.READ_EXTERNAL_STORAGE, checkPermissionCallback, null);

        function checkPermissionCallback(status) {
            if (!status.hasPermission) {
                var errorCallback = function () {
                    console.warn('Storage permission is not turned on');
                }
                permissions.requestPermission(
                  permissions.READ_EXTERNAL_STORAGE,
                  function (status) {
                      if (!status.hasPermission) {
                          errorCallback();
                      } else {
                          // continue with downloading/ Accessing operation 
                          $scope.downloadFile();
                      }
                  },
                  errorCallback);
            }
        }

Monday, August 8, 2016

Deferred long-running timer task(s) to improve scrolling smoothness : IONIC

I recently encountered this warring message during the ionic application deployment. In the application console
Deferred long-running timer task(s) to improve scrolling smoothness warring message was keep popping out. After an investigation I found that error was throwing due
$timeout service in angular.


$scope.searchTimer = $timeout(function () { 
    $scope.initiateSearch(true); 
 }, 500); //wait .5 seconds after the user finished typing.

The reason was I was doing a task using a timer. To get rid of this warning message, I had to destroy it after using it. Therefore I used $destroy event to kill the timer.

$scope.$on( 
   "$destroy", 
    function( event ) { 
    $timeout.cancel( timer ); 
 });