Showing posts with label TypeScript. Show all posts
Showing posts with label TypeScript. Show all posts

Wednesday, August 1, 2018

Rest Parameters in TypeScript

In TypeScript, Rest Parameters are often used in functions to specify the parameters when the number of parameters is unknown.

Let’s go by a sample scenario. Imagine we need to have a method which will return us the full address (nicely separated by “,”) when different parts of the address are supplied. Some addresses have Address Line 1, Address Line 2 etc., and for some, there is no Address Line 2, likewise.

In this case, there is no fixed number of parameters. To cater such a requirement, we can have the following function with Rest Parameters.
function buildAddress(...addressLines) {
    return addressLines.join(", ");
};
Here the Rest Parameter is the addressLines, we are using JavaScript split operator (ellipsis) to specify that.

With TypeScript it’s always better to be explicit. You can specify the type of the Rest Parameters as well. And note, it should always be an array type as behind the scene it really is an array.
function buildAddress(...addressLines: string[]) {
    return addressLines.join(", ");
};
We can call the function like below.
console.log(buildAddress("111-2222", "Bing Street", "Springfield Gardens", "NY", "33333"));
// 111-2222, Bing Street, Springfield Gardens, NY, 33333

console.log(buildAddress("111-2222", "Springfield Gardens", "NY", "33333"));
// 111-2222, Springfield Gardens, NY, 33333
And you can even not pass anything at all.
console.log(buildAddress());
Isn’t it nice!

Happy Coding.

Regards,
Jaliya

Thursday, February 16, 2017

Creating a MVC ASP.NET Core Application Powered by React

Recently I have started to explore React and this morning, I saw this blog post Building Single Page Applications on ASP.NET Core with JavaScriptServices published on .NET Web Development and Tools Blog. And when I started to read this post, I got quite surprised and amazed.

Basically the summary is with the latest version of .NET Core SDK, you can use following templates to create a project using dotnet new.
image
dotnet new --list
While there are a lot of information about all of this in above mentioned post, in this post, I am going to explore the React project template. (Not React with Redux, at least not on this post). Of course, to start exploring , first you need to create it.

I have the latest .NET Core SDK and Node installed.
image
dotnet  and Node version
And I have installed Single Page Application (SPA) templates as per the original blog post.
Now let’s start some React time.
image
dotnet new react
Once the project is created, let’s see what dotnet exactly has created for us.
image
Project Structure
You can see that basically the structure is more or less the same to web application projects created using Visual Studio.

In addition you have webpack, babel and TypeScript configuration files (if you haven’t worked with webpack, and babel before, may be you can read this previous post of mine: Getting Started with React, Babel and Webpack). And of course there is a Dockerfile as well.

Your familiar files which bootstraps ASP.NET Core and MVC (Program.cs, Startup.cs, Controllers and Views folders etc.) are there. React components are placed inside ClientApp folder.

While all the client side dependencies are listed in package.json, server side dependencies are listed in the .csproj it self (you can find more information about the project.json to .csproj migration in this previous post of mine: Where is project.json in Default .NET Core Application Templates in Visual Studio 2017). On the server side dependencies, one of the important thing to note is, reference to “Microsoft.AspNetCore.SpaServices”.

image
Server Side Dependencies
If you open up Startup.cs, inside Configure method which configures the HTTP request pipeline, while the environment is Development, we are using the Webpack Dev Server along with it’s HMR (Hot Module Replacement) feature.
image
Use of Webpack Dev Server
This is made all possible by using “Microsoft.AspNetCore.SpaServices” package.  And that is a very handy thing when it comes to development, you don’t have to refresh the page after making client side code changes.

So now let’s run the application and see what happens. Open up a command prompt inside the project folder and run the following commands to restore/install server side and client side packages.
dotnet restore
npm install
Finally it’s the command of joy.
dotnet run
image
dotnet run
Let’s navigate to http://localhost:5000 from the browser.
image
MVC ASP.NET Core with React
Isn’t it marvelous!

Happy Coding.

Regards,
Jaliya

Monday, August 15, 2016

Angular 2 with TypeScript on top of ASP.NET Core using Visual Studio 2015

In this post let’s see how we can setup a very basic Angular 2 application with TypeScript on top of ASP.NET Core using Visual Studio 2015.

This post is totally based on the official sample used in 5 MIN QUICKSTART using Angular 2 for TypeScript which is available in following URL.
I will not be going into deeper descriptions here because above mentioned article almost explains everything. I will be adopting the code used in the same article and will be doing modifications on the go to match my requirements.

Without further ado, let’s start by firing up Visual Studio 2015 and creating an ASP.NET Core Web Application. Please note that I have installed Node.js and npm.
image
ASP.NET Core Web Application
image
Empty Template
Now open up the startup.cs and modify the code as follows.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
 
namespace AspNetCoreAngular2TypeScriptDemo
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }
 
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();
 
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
 
            app.UseDefaultFiles();
            app.UseStaticFiles();
        }
    }
}
You may need to install "Microsoft.AspNetCore.StaticFiles" dependency and add necessary usings. Here I have specified app.UseDefaultFiles() to server a default file and app.UseStaticFiles() to enable static file serving.

Right click on the project and add a new JSON file named “typings.json”.

typings.json
{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160602141332",
    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
    "node": "registry:dt/node#6.0.0+20160807145350"
  }
}
A file named typings.json is needed to install typings, otherwise npm will throw a warning saying no typings.json is found.

Right click on the project and add npm Configuration File.
image
npm Configuration File
package.json
{
  "version": "1.0.0",
  "name": "AspNetCoreAngular2TypeScriptDemo",
  "scripts": {
    "postinstall": "typings install",
    "typings": "typings"
  },
  "private": true,
  "dependencies": {
    "@angular/common": "2.0.0-rc.5",
    "@angular/compiler": "2.0.0-rc.5",
    "@angular/core": "2.0.0-rc.5",
    "@angular/forms": "0.3.0",
    "@angular/http": "2.0.0-rc.5",
    "@angular/platform-browser": "2.0.0-rc.5",
    "@angular/platform-browser-dynamic": "2.0.0-rc.5",
    "@angular/router": "3.0.0-rc.1",
    "@angular/router-deprecated": "2.0.0-rc.2",
    "@angular/upgrade": "2.0.0-rc.5",
    "systemjs": "0.19.36",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "^0.6.12",
    "bootstrap": "^3.3.7"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "del": "^2.2.1"
  }
}
Here I did some modifications to make it simpler. You can see that in postinstall (after all the packages are installed), I have set to run typings install command. Now when you restore/install npm packages, you can see that upon all the packages are completed installing, npm is running typings install. It will create a folder named typings which will contain TypeScript definition files. To see the npm progress, open up output window and Select output from Bower/npm.

Right click on the project and add TypeScript JSON Configuration File.
image
TypeScript JSON Configuration File
tsconfig.json
{
  "compilerOptions": {
    "noImplicitAny": true,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "experimentalDecorators": true
  },
  "compileOnSave": true
}
I have compileOnSave enabled, so every time I save my TypeScript files, TypeScript to JavaScript compilation will be done.

Right click on the project and add Gulp Configuration File.
image
Gulp Configuration File
gulpfile.js
var gulp = require('gulp');
var del = require('del');
 
var paths = {
    nodeModules: 'node_modules/**/*.js'
};
 
gulp.task('clean', function () {
    return del(['wwwroot/scripts/**/*']);
});
 
gulp.task('build', function () {
    gulp.src(paths.nodeModules).pipe(gulp.dest('wwwroot/scripts'))
});
I have 2 tasks, build task to copy all the node_modules to a folder named scripts inside wwwroot and clean task to delete all content inside scripts folder. This is just for the demonstration, may be you can have a task to clean up JavaScript files which gets created upon compiling TypeScript files.

Run the build task by right clicking on gulpfile.js -> Task Runner Explorer.
image
Task Runner Explorer
Upon task completion, you can see a new folder named scripts created under wwwroot. You can see all your node_modules copied into scripts folder.

Create a folder inside wwwroot named app and create following three TypeScript files, app.component.ts, app.module.ts and main.ts  over there.

app.component.ts
import { Component } from '@angular/core';
@Component({
    selector: 'my-app',
    template: '<h1>Welcome to Angular 2 with TypeScript</h1>'
})
export class AppComponent { }
app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
 
import { AppComponent }  from './app.component';
 
@NgModule({
    imports: [BrowserModule],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
As in the original example, we are using systemjs to dynamically load modules. Add a JavaScript file named systemjs.config.js inside wwwroot folder.
image
systemjs.config.js
systemjs.config.js
(function (global) {
    // map tells the System loader where to look for things
    var map = {
        'app': 'app', // 'dist',
        '@angular': 'scripts/@angular',
        'rxjs': 'scripts/rxjs'
    };
    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app': { main: 'main.js', defaultExtension: 'js' },
        'rxjs': { defaultExtension: 'js' }
    };
    var ngPackageNames = [
      'common',
      'compiler',
      'core',
      'forms',
      'http',
      'platform-browser',
      'platform-browser-dynamic',
      'router',
      'router-deprecated',
      'upgrade',
    ];
    // Individual files (~300 requests):
    function packIndex(pkgName) {
        packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
    }
    // Bundled (~40 requests):
    function packUmd(pkgName) {
        packages['@angular/' + pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
    }
    // Most environments should use UMD; some (Karma) need the individual index files
    var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
    // Add package entries for angular packages
    ngPackageNames.forEach(setPackageConfig);
    var config = {
        map: map,
        packages: packages
    };
    System.config(config);
})(this);
Add index.html file inside wwwroot folder.

index.html
<html>
<head>
    <title>AspNetCoreAngular2TypeScriptDemo</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
 
    <!-- 1. Load libraries -->
    <!-- Polyfill(s) for older browsers -->
 
    <script src="scripts/core-js/client/shim.min.js"></script>
    <script src="scripts/zone.js/dist/zone.js"></script>
    <script src="scripts/reflect-metadata/Reflect.js"></script>
    <script src="scripts/systemjs/dist/system.src.js"></script>
 
    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function(err){ console.error(err); });
    </script>
</head>
 
<!-- 3. Display the application -->
<body>
    <my-app>Loading...</my-app>
</body>
</html>

Now we are all good. Compile and run the project.
image
Output
It's working.

I have pushed the project into a GitHub repository and please do play around.

Happy Coding.

Regards,
Jaliya