Underscore.JS: Access local variables and function inside each function of UnderscoreJS in Typescript

Standard

While using AngularJS with Typescript, I witnessed the scenario, where my function is accessing variables and functions defined in controller constructor, to make life easy for some collection manipulation, I used underscoreJS helper functions, _.each

_.each(data, function(item : any) {
     item.name = this.formatName(item);
});

Everything was on track, except I was unable to access local variables and functions(this.formatName) defined in the angular controller in underscoreJS _.each, I was getting an undefined error for this.formatName method inside _.each.

Solution:

As you are aware of the fact that ‘this‘ keyword behaves differently in JavaScript compared to other languages. For Typescript, ‘this‘ keyword refers to the current instance of the class. In JavaScript, the value of ‘this‘ is determined mostly by the invocation context of the function and where it is called. (Read this reference)

  1. In order to resolve this problem, inject ‘this‘ as context by setting it up as the third parameter to _.each helper function
_.each(data, function(item : any) {
     item.name = this.formatName(item);
}, this);

2. There is one more solution too by saving the context in temporary variable before consuming ‘this’ in _.each

public testFunction() : void {
  var context = this;
  _.each(data, function(item : any) {
      item.name = context.formatName(item);
  });
}

 

Advertisements

AngularJS: Error – Argument of type ‘RegExp’ is not assignable to parameter of type ‘string’

Standard

While working on a test project in AngularJS with Typescript, I came across this specific error:

Argument of type 'RegExp' is not assignable to parameter of type 'string'

Code:

let expression = new RegExp(/(test)=\(A:([0-9.]*)\)/g);

The problem is that I am duplicating the initialization process of Regex, first, it set up regular expression by standard syntax (/ /g) and then re-setup regular expression using constructor ( new RegExp() )

Solution 1:

let expression = /(test)=\(A:([0-9.]*)\)/g;

Solution 2:

let expression = new RegExp('(test)=\(A:([0-9.]*)\)', 'g');

 

AngularJS: Add line-break or HTML Elements in Angular Bootstrap UI Tooltip

Standard

In order to add line-break in tool-tip content for angular bootstrap tool-tip component, Please try to understand, There are three versions of the tool-tip: uib-tooltip, uib-tooltip-template, and uib-tooltip-html:

  • uib-tooltip – Takes text only and will escape any HTML provided.
  • uib-tooltip-html $ – Takes an expression that evaluates to an HTML string. Note that this HTML is not compiled. If compilation is required, please use the uib-tooltip-template attribute option instead. The user is responsible for ensuring the content is safe to put into the DOM!
  • uib-tooltip-template $ – Takes text that specifies the location of a template to use for the tooltip. Note that this needs to be wrapped in a tag.
    Reference

In order to add HTML element like <br> for new line/line-break use uib-tooltip-html instead of uib-tooltip, make sure you have enabled $sceProvider in module config and injected $sce in relevant controller.

$sceProvider

The $sceProvider provider allows developers to configure the $sce service.

  • enable/disable Strict Contextual Escaping (SCE) in a module
  • override the default implementation with a custom delegate

$sce

$sce is a service that provides Strict Contextual Escaping services to AngularJS.

Strict Contextual Escaping (SCE) is a mode in which AngularJS constrains bindings to only render trusted values. Its goal is to assist in writing code in a way that (a) is secure by default, and (b) makes auditing for security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
Reference

Module/Controller Code:

var app = angular
                .module("tooltipApp", ['ui.bootstrap'])
                .config(function($sceProvider) {
                          $sceProvider.enabled(false);
                });

app.controller("tooltipController", function($scope, $sce) {
    $scope.tooltipContent = $sce.trustAsHtml('Hello World </br></br>' + 
                                             'Dummy content after line-break ');
});

HTML Code:

<span ng-app="test" ng-controller="tooltipController">
    <span uib-tooltip-html="tooltipContent">
        Tooltip Content
    </span>
</span>

Output:

Angular2: Custom toaster / notification service using Angular2 Material Snackbar Component

Standard

Since toasters/notifications are essential component for any connected web application, we have couple of toasters component available in market for angular2, I am using Angular Material Snackbar component.

Usage

Since toasters/notifications are used throughout the application, so its better to define as unified service and then consume it throughout application by injecting service in various controllers.

Pre-Step:

  • Install Angular Material components
npm install --save @angular/material
  • Import the Angular Material NgModule in src/app/app.module.ts
import { MaterialModule } from '@angular/material';
// other imports 
@NgModule({
  imports: [MaterialModule],
  ...
})
export class PizzaPartyAppModule { }
  • Some of the components like md-slide-toggle, md-slider, mdTooltip rely on HammerJS for gestures
npm install --save hammerjs

After installing, import HammerJS on your app’s module. src/app/app.module.ts

import 'hammerjs';
  • If your project is using SystemJS for module loading, you will need to add @angular/material to the SystemJS configuration:
System.config({
  // existing configuration options
  map: {
    ...,
    '@angular/material': 'npm:@angular/material/bundles/material.umd.js'
  }
});

Reference

Step 1 : Create angular material toaster service IN toaster.service.ts:

import { Injectable } from '@angular/core';
import { MdSnackBar } from '@angular/material';

@Injectable()
export class ToasterService {

    constructor(private snackBar: MdSnackBar) {
    }

    showToaster(msg: string) {
        this.snackBar.open(msg, null, {
            duration: 3000,
        });
    }
}

A snack-bar can contain either a string message or a given component.

// Simple message.
let snackBarRef = snackBar.open('Message archived');

// Simple message with an action.
let snackBarRef = snackBar.open('Message archived', 'Undo');

// Load the given component into the snack-bar.
let snackBarRef = snackbar.openFromComponent(MessageArchivedComponent);

Step 2: Register toaster service to main module IN app.module.ts:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { MaterialModule } from '@angular/material';
import 'node_modules/hammerjs/hammer.js';

import { AppComponent } from './app.component';
import { CustomComponent } from './custom.component';
import { ToasterService } from './shared/service/toaster.service';

@NgModule({
    imports: [
        //angular builtin module
        BrowserModule,

        //ui module
        MaterialModule.forRoot()
    ],
    declarations: [
        AppComponent,
        CustomComponent 
    ],
    providers: [
        ToasterService
    ],
    bootstrap: [
        AppComponent
    ],
    schemas: [
        CUSTOM_ELEMENTS_SCHEMA
    ]
})

export class AppModule {
}

Step 3: Inject toaster service in controller, let say custom.component.ts:

import { Component, OnInit } from '@angular/core';
import { ToasterService } from '../toaster.service';

@Component({
    selector: 'search-movie',
    templateUrl: '../custom.component.html'
})

export class CustomComponent implements OnInit {

    constructor(
        private toasterService: ToasterService) {
    }

    ngOnInit() {
        this.toasterService.showToaster('Hello World');
    }
}

Output:

 

 

Angular2: Using custom loader / spinner as service in Angular 2 application

Standard

Since loaders/spinners are essential component for any connected web application, we have couple of spinner component available in market for angular2. For spinner’s css, I am using Absolute Center CSS Overlay Spinner By MattIn4D

Usage

Since spinner is used throughout the application, so its better to define it once in index.html and then try to enable/disable through component code. I am also using BehaviorSubject object in service, which is way more awesome and better then observable in many cases, Behavior Subject is a special type of observable so you can subscribe to messages like any other observable. In plain words the variable controlling enabling and disabling the spinner in index.html can be set and observed in service using BehaviorSubject object.

Step 1 : Copy spinner css IN app.component.css file:

.tootlbar-icon {
  padding: 0 14px;
}

.tootlbar-spacer {
  flex: 1 1 auto;
}

/* Absolute Center Spinner */
.loading {
  position: fixed;
  z-index: 999;
  height: 2em;
  width: 2em;
  overflow: show;
  margin: auto;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

/* Transparent Overlay */
.loading:before {
  content: '';
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,0.3);
}

/* :not(:required) hides these rules from IE9 and below */
.loading:not(:required) {
  /* hide "loading..." text */
  font: 0/0 a;
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}

.loading:not(:required):after {
  content: '';
  display: block;
  font-size: 10px;
  width: 1em;
  height: 1em;
  margin-top: -0.5em;
  -webkit-animation: spinner 1500ms infinite linear;
  -moz-animation: spinner 1500ms infinite linear;
  -ms-animation: spinner 1500ms infinite linear;
  -o-animation: spinner 1500ms infinite linear;
  animation: spinner 1500ms infinite linear;
  border-radius: 0.5em;
  -webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
  box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
}

/* Animation */

@-webkit-keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@-moz-keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@-o-keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

Step 2 : Create angular material spinner service IN loader.service.ts:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class LoaderService {
    public status: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

    display(value: boolean) {
        this.status.next(value);
    }
}

Step 3: Register loader service to main module IN app.module.ts:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { MaterialModule } from '@angular/material';
import 'node_modules/hammerjs/hammer.js';

import { AppComponent } from './app.component';
import { CustomComponent } from './custom.component';
import { LoaderService } from './shared/service/loader.service';

@NgModule({
    imports: [
        //angular builtin module
        BrowserModule,

        //ui module
        MaterialModule.forRoot()
    ],
    declarations: [
        AppComponent,
        CustomComponent 
    ],
    providers: [
        LoaderService
    ],
    bootstrap: [
        AppComponent
    ],
    schemas: [
        CUSTOM_ELEMENTS_SCHEMA
    ]
})

export class AppModule {
}

Step 4 : Register spinner html inside router-outlet to have its impact on all components IN app.component.html

<router-outlet>
    <span*ngIf="showLoader" class="loading"></span>
</router-outlet>
*wordpress text editor has issue with div tag, you can replace span with tag

Step 5: Inject toaster service inside app.component.ts to show or hide loader

import { Component, OnInit } from '@angular/core';

import { LoaderService } from './shared/service/loader.service';

@Component({
    selector: 'my-app',
    templateUrl: './app/app.component.html',
    styleUrls: ['./app/app.component.css']
})

export class AppComponent implements OnInit {
    showLoader: boolean;

    constructor(
        private loaderService: LoaderService) {
    }

    ngOnInit() {
        this.loaderService.status.subscribe((val: boolean) => {
            this.showLoader = val;
        });
    }
}

Step 6: Consume loader service in controller custom.component.ts:

Just pass ‘true’ in order to display the loader and ‘false’ in order to hide the loader

import { Component, OnInit } from '@angular/core';
import { LoaderService } from '../loader.service';

@Component({
    selector: 'search-movie',
    templateUrl: '../custom.component.html'
})

export class CustomComponent implements OnInit {

    constructor(
        private loaderService: LoaderService) {
    }

    ngOnInit() {
        //http call starts
        this.loaderService.display(true);
        //http call ends
        this.loaderService.display(false);
    }
}

Output:

 

Angular2: Resolve TS5023 Build:Unknown compiler option ‘typeRoots’ and ‘types’ error in Visual Studio

Standard

I installed fresh copy of Visual Studio 2015 update 3 on my secondary machine and try to execute Angular2 project integrated with ASP.NET CORE and came across an issue

TS5023 Build:Unknown compiler option 'typeRoots'
TS5023 Build:Unknown compiler option 'types'

Solution 1:

In VS2015 go to:

Tools -> Options -> Projects and Solutions -> External Web Tools.

uncheck anything that starts with $(VSINSTALLDIR)

Solution 2 (recommended):

Before trying any other option, I just updated Typescript version installed for VS2015 from 2.0.3 to 2.2.0 and this resolve compiler option error, Upgrade to latest version of Typescript by installing executable from MS Official Download link.

ASP.NET CORE: Sending Email with Gmail and Homtail Account using ASP.NET Core services

Standard

Sending email from any SMTP server from ASP.NET CORE application is pretty easy, but the flow of command is slight different in core environment.

Gmail SMTP server address is smtp.gmail.com. It requires implicit SSL or explicit SSL (TLS) connection, and you should use your Gmail email address as the user name for ESMTP authentication.

So basically we will read email smtp address, port, username and password from appsettings.json, then will inject these config to email service class, in the end we will inject email service class to controller and consumer email send operation.

Step 1: Define email specific information in appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": ""
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "EmailSettings": {
    "PrimaryDomain": "smtp.gmail.com",
    "PrimaryPort": "587",
    "SecondayDomain": "smtp.live.com",
    "SecondaryPort": "587",
    "UsernameEmail": "emailId@gmail.com",
    "UsernamePassword": "emailPassword",
    "FromEmail": "fromEmail",
    "ToEmail": "toEmail",
    "CcEmail": "ccEmail"
  }
}

SmtpServer: The name of the server that will be used to send the emails.

SmtpPort: The port, which the server will use to send SMTP transactions (emails).

EnableSsl: True, if the server should use SSL (Secure Socket Layer) encryption.

Smtp Server Address and Port #

Server Name SMTP Address Port SSL
Yahoo! smtp.mail.yahoo.com 587 Yes
GMail smtp.gmail.com 587 Yes
Hotmail smtp.live.com 587 Yes

Step 2: Create a class to encapsulate EmailSettings properties from appsettings.json

public class EmailSettings
    {
        public String PrimaryDomain { get; set; }

        public int PrimaryPort { get; set; }

        public String SecondayDomain { get; set; }

        public int SecondaryPort { get; set; }

        public String UsernameEmail { get; set; }

        public String UsernamePassword { get; set; }

        public String FromEmail { get; set; }

        public String ToEmail { get; set; }

        public String CcEmail { get; set; }
    }

Step 3: Register class in startup.cs for DI purposes

services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));

Step 4: Create an Email sender interface

public interface IEmailSender
{
    Task SendEmailAsync(string email, string subject, string message);
}

Step 5: Create a message service class which will implement this interface

Inject EmailSettings class in message service using options pattern, so that email configuration defined in appsettings.json is available in this service.

We will use SmtpClient class to allow applications to send e-mail by using the Simple Mail Transfer Protocol (SMTP).

public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<EmailSettings> emailSettings)
        {
            _emailSettings = emailSettings.Value;
        }

        public EmailSettings _emailSettings { get; }

        public Task SendEmailAsync(string email, string subject, string message)
        {

            Execute (email, subject, message).Wait();
            return Task.FromResult(0);
        }

        public async Task Execute(string email, string subject, string message)
        {
          try
          {
            string toEmail = string.IsNullOrEmpty(email) 
                             ? _emailSettings.ToEmail 
                             : email;
            MailMessage mail = new MailMessage()
            {
                From = new MailAddress(_emailSettings.UsernameEmail, "Muhammad Hassan Tariq")
            };
            mail.To.Add(new MailAddress(toEmail));
            mail.CC.Add(new MailAddress(_emailSettings.CcEmail));

            mail.Subject = "Personal Management System - " + subject;
            mail.Body = message;
            mail.IsBodyHtml = true;
            mail.Priority = MailPriority.High;

            using (SmtpClient smtp = new SmtpClient(_emailSettings.SecondayDomain, _emailSettings.SecondaryPort))
            {
                smtp.Credentials = new NetworkCredential(_emailSettings.UsernameEmail, _emailSettings.UsernamePassword);
                smtp.EnableSsl = true;
                await smtp.SendMailAsync(mail);
            }
          }
          catch(Exception ex)
          {
             //do something here
          }
        }
    }

*exception handling is left for you to implement 🙂

  • You can attach one or several files:
mail.Attachments.Add(new Attachment(Server.MapPath("~/myimage.jpg")));
  • You can send to more than one person at the same time
mail.To.Add("test@email.com");
mail.To.Add("test2@email.com");
  • You can set a name for the sender
mail.From = new MailAddress("test@email.com", "Hello");
  • You can send HTML e-mails, instead of the default plaintext mails
mail.IsBodyHtml = true;
mail.Body = "Testing <b>123!</b>";
  • You can use the CC and BCC fields
mail.CC.Add("test@email.com");
mail.Bcc.Add("test2@email.com");
  • You can set the priority of an e-mail
mail.Priority = MailPriority.High;

Step 6: Register email sender service in startup.cs, so that it can be injected in controllers

services.AddTransient<IEmailSender, AuthMessageSender>();

Step 7: Controller code (consumer)

Inject email sender service in controller constructor and then invoke SendEmailAsync method of it

public class TestController : Controller
    {
        private readonly IEmailSender _emailSender;

        public AccountController(IEmailSender emailSender)
        {
            _emailSender = emailSender;
        }
        
        public async Task TestAction()
        {
           await _emailSender.SendEmailAsync("test@gmail.com", "subject",
                        $"Enter email body here");
        }
    }

Note:

Google may block sign in attempts from some apps or devices that do not use modern security standards. Since these apps and devices are easier to break into, blocking them helps keep your account safer.

Please make sure, in Gmail settings of your account, enable access for less secure apps to avoid below error:

The SMTP server requires a secure connection or the client was not 
authenticated. The server response was: 5.5.1 Authentication Required?