Category Archives: Programming

Getting started with NodeJS – Part 1: Fumbling around

I’ve been meaning to try out NodeJS for a while now, and finally got around to doing it over the last few days. I thought I would share my experience as I go along.

Update: Those ‘few days ago’ are actually a couple of months now 😉

I have used NodeJS as a (build) tool to help me ‘compile’ front-end scripts, that involves taking dev source code and minifiying it into cache-busted deployable code. I use gulp for it and it works pretty okay. Fact is, while writing the gulp script I got pretty interested in NodeJS.

Also given the fact that ASP.NET vNext is pretty much going the ‘Node way’, I thought I should know what the real deal is, before I muck around with ASP.NET vNext.

So here is my first go at building ‘something’ using NodeJS as a platform as opposed to just a Dev/Build tool. The article expects you to have heard of NodeJS and NPM (Node Package Manager, something like Nuget but runs off the command line and available to both Windows and *nix). If you have never used either of them, it’s fine.

Environment

OS

Debian 8 (Jessie).

My readers using Windows fear not, you can use NodeJS on Windows using nearly the same steps, so if you get stuck just let me know and I’ll try and help.

NodeJS:

node --version

v4.2.1

npm --version

2.14.7

Side note on upgrading Node in Debian: If you read my previous article I had mentioned Jessie comes with a Node package by default, but it’s a rather old one. I un-installed that one using

sudo apt-get remove nodejs

Thereafter I followed the step outlined on Nodejs.org . Reproduced here

curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -

sudo apt-get install -y nodejs

This basically downloads the latest package from the official node repository and installs it.

Windows Users: Just get the latest Node installers from nodejs.org and rock on! NPM is installed as a part of Node.
OSX Users: You guys are all good, just install Node and the rest of the commands should be all the same.

IDE/Editor

Well, you could use anything you want, starting with Visual Studio full on, to Visual Studio Code, or any other IDE/Editor that suits your fancy. I am using Atom by Github. I am new to Atom as well, so there might be some moments when the experienced Atom user in you wince at my noobish-ness.

The Project

Well, I want to figure out what it takes to use QuillJS wrapped in a KO Component and then save the text in component into Azure Blob Storage. Simple right ;-). The project is called ParchmentScroll. Why? Well you use quills to write Scrolls on Parchment paper… 😉 😉 😉

Oh, BTW, QuillJS is a really cool JavaScript library for add Rich Text capabilities to your Web Application. It was open sourced by Sales Force and is available under a permissive BSD license.

So lets get started, but before that lets try wrapping our head around ‘Server-side’ JavaScript.

JavaScript… umm… TypeScript everywhere (client-side and server-side)

You either love JavaScript or loathe it! I have made my peace with it and I kind of like its dynamic quirkiness. After I started using TypeScript I like JavaScript even better.

Anyway, traditionally we all know how to use JavaScript in the browser. But Node JS takes JavaScript and runs it through Google’s V8 engine on the server so you can actually write HTTP services in JavaScript. So you can have a HTML page hosted on IIS, NGINX, Apache or wherever, do an AJAX post to your NodeJS application that you’ve written in JavaScript and send back a response. To put things in contrast with the .NET world, think of writing Web API services, but instead of writing ApiControllers in C# you get to write it in JavaScript.. err TypeScript!!!

Down to some code… err well… kind of

Since I am using Atom, a lot of the steps I describe here, to setup a blank project, will look long drawn, when compared to Visual Studio’s File->New Project->Wizard->Done.

So lets get started.

Open a terminal.

Select/Create your favourite project folder and navigate to it. Mine is at

cd /home/sumitkm/myprojects/demo/parchmentscroll

Packages, their managers and Node JS

The NodeJS ecosystem thrives on a huge repository of third party libraries that are distributed as packages. Packages inherit the idea of Linux packages. They bundle self contained units of code/binaries that can be installed and updated using their respective package managers.

In this project I have used three package managers

1. The Node Package Manager aka npm – This is Node’s default package manager and is used to distribute all node packages, binaries and extensions. Fun fact, you use npm to install other package managers :-). So npm is the alpha dog of package managers in Node and is installed by default with Node. Node packages are mostly used for installing dependencies that you will use on the server side. For client side Script/style dependencies you use the next package manager – Bower.

2. Bower – The front-end package manager. Bower installs front-end dependencies that are mostly distributable versions of the libraries or frameworks that you will use e.g. KnockoutJS, RequireJS, QuillJS etc. To get started with Bower you first need to install it using npm at the global npm repository location as follows.

Please note if you are are not the administrator but have sudo-er rights, you need to prepend sudo to every shell command unless I say you don’t need one explicitly.

npm install bower -g

3. TSD – The TypeScript Definitions package manager. While the good thing about TypeScript is it provides better code management due to type enforcement at compile time, the flip side is you need TypeDefinitions for existing libraries written in ES3-4. DefinitelyTyped is a nice Open Source repository of TypeDefinitions that users have contributed as they have used existing libraries. While creating a TypeDefinition is relatively easy, its good to have a leg up with the existing libraries. So we install TSD a package manager that helps you retrieve type definitions for libraries you will use from the DefinitielyTyped repository

npm install tsd -g

We start by initializing an NPM ‘project’. This creates a package.json file which has the list of dependencies as well as details like the Project Name, version, Git repository, Author name, License information etc.

npm init

(don’t use sudo here)

This will present you with a series of prompts where you provide the requested details and it will in turn scaffold a package.json file for you. I provided the following details:

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install  --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (parchmentscroll) 
version: (1.0.0) 
description: A blogging platform built using Node, QuillJS and TypeScript
entry point: (index.js) 
test command: 
git repository: https://github.com/sumitkm/parchmentscrolldemo/
keywords: QuillJS, NodeJS, TypeScript
author: Sumit Kumar Maitra
license: (ISC) MIT
About to write to /home/sumitkm/myprojects/demo/parchmentscroll/package.json:
{
  "name": "parchmentscroll",
  "version": "1.0.0",
  "description": "A blogging platform built using Node, QuillJS and TypeScript",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/sumitkm/parchmentscrolldemo/"
  },
  "keywords": [
    "QuillJS",
    "NodeJS",
    "TypeScript"
  ],
  "author": "Sumit Kumar Maitra",
  "license": "MIT"
}
Is this ok? (yes) yes

If you do ls now, you’ll see that a package.json file exists in the folder.

Here on, you have to decide your project structure. There are lots of sensible defaults, you can look up on the net. I am trying out one that I feel comfortable with. I may change it as we go along and build the project.

Since there are no csproj files or equivalent (package.json is a distant cousin, more like a .sln file than anything else), I am going to create top level folders as projects. So I create two main folders

(no sudo required)

mkdir www

mkdir server

Next will initialize the typescript definition file tsconfig.json
(no sudo required)

tsc --init

This creates a TypeScript config file that helps TypeScript compiler with location of the ts files in the project and other configuration items. If you open the file in an editor you’ll see the default:

{
"compilerOptions": {
"module": "commonjs",
"target": "es3",
"noImplicitAny": false,
"outDir": "built",
"rootDir": ".",
"sourceMap": false
},
"exclude": [
"node_modules"
]
}

 

The compiler options are same ones available via command line. I tend to remove the outDir attribute completely. This results in the .js files being generated in the same folder as the .ts file. This fits better with my deploy script that we’ll see sometime in the future.

The exclude array tells typescript compiler which folder it shouldn’t look at. Currently only node_modules is excluded.

The final tsconfig.json file we are starting with is

 

"compilerOptions": 
 {
  "module": "commonjs",
  "target": "es3",
  "noImplicitAny": false,
  "rootDir": ".",
  "sourceMap": true
 },
 "exclude": [
   "node_modules"
  ]
 }

This completes our ‘File->New Project’. Here on we’ll get on with some real code.

Application layout in a little more details

In the previous section we created two folder server and www as our two ‘projects’. The server folder will be root folder for all the server side logic and the www folder will hold whatever resources the browser needs to serve up the web page. So folder names basically help us with a mental segregation of what goes where.

 

Node JS can open ports and server content on ports if you want it to. But we don’t want to go that low level. Instead we’ll get help from a framework called Express JS to the low level stuff of opening/listening to ports, parsing requests, sending back responses etc. Basically we’ll use ExpressJS to bootstrap the application. The handy bit is, Express can serve up static files as well, so we’ll use the same framework to host the front-end and handle backend request/responses.

Down to some code, finally!

Getting started with ExpressJS

Setting up anything in node basically means npm –install. Express is no different. In the ‘parchmentscroll’ folder using the following

npm install express --save 

Save tells npm to update the package.json file with this particular dependency. So when you get sources on to a new folder all you have to do is npm install and all dependencies listed in package.json will be installed for you.

Time to start up Atom in the parchmentscroll folder enter

(no sudo required)

atom .

This should launch atom with the following layout

new-project-atom-editor
Under the server folder create a folder called app

Add app.ts file under app folder. This is going to be our entry point into the application.

But before we start writing code, we need a little more ‘configuration’ to do.

Back to the console in the parchmentscroll folder we’ll use the tsd package manager to install typescript definitions for node itself
(no sudo required)

tsd query node --action install --save

This tells tsd to look for the node type definition and if found install it and save it to tsd.json

Similarly we install typedefinitions for ExpressJS as well

ts query express --action install --save

Next we’ll install a couple of npm modules that Express JS uses for parsing a request body and serving up static files.

npm install body-parser

npm install serve-static

We also need the typescript definition for these two, so invoke tsd again –

tsd query --action install serve-static --save --

tsd query --action install body-parser --save --resolve

Note the — resolve flag that we’ve used in the above two commands. This tells tsd to resolve sub-dependencies of the library and get their type-definitions as well. You’ll note both use another dependency call mime that gets installed automatically.

Back to Atom in app.ts paste the following code and save the file.

/// <reference path="../../typings/tsd.d.ts"/>
import * as express from "express";
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(express.static('www/'));
var server = app.listen(3001, () =>
{
 var host = server.address().address;
 var port = server.address().port;
 console.log('Example app listening at http://%s:%s', host, port);
});

– This code initializes express.
– Initializes an instance of the body parser module and sets it up to handle HTTP request body of type application/json

– Sets up the bodyParser module to handle parsing of url encoded HTTP requests

– Sets up express to handle static files in the ‘www’ folder (which is currently empty).

– Finally it setup up the express instance to listen to port 3001 and once the server starts print out a console message.
With the code setup, switch back to the terminal and in the parchmentscroll folder run tsc.

tsc 

The code should compile silently and come back with no messages.

Next we try to run the app using the following command

node .

The . tells Node to use the package.json to start up. However you’ll get an error at this point.

Error: Cannot find module '/home/sumitkm/myprojects/demo/parchmentscroll'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:289:25)
at Function.Module.runMain (module.js:467:10)
at startup (node.js:136:18)
at node.js:963:3

This because when we setup our package.json we said index.js was our ‘main’ file. Problem, easily fixed, switch to Atom and open package.json.

Set the “main” attribute to “server/app/app.js” instead of the initial “index.js”.

Save the file and flip back to the terminal. Run node . Again

node .

This time you should see a message like the following:

Example app listening at http://:::3001

If you open your browser and go to localhost:3001/ you’ll get a message saying “Can’t GET /”

So switch back to Atom and add a file under www called
index.html.

Add a bit of hello world markup

<!DOCUMENT>
<body>
Hello Node JS
</body>

Save the file.

Refresh the browser and voila!

 

first-node-js-hello-world
Phew! Lot of work for a Hello World!

To sum up…

That may have seemed a lot of work up-front but all of it can be automated and scaffold-ed if we wanted to. Open source tool chains are much lighter weight when compared to enterprise apps like Visual Studio. However, they give you a lot more freedom to mix and match and hey all of them are actually free without you signing away your keystrokes in some EULA.

We have not even scratched the surface on NodeJS yet. In the next part, I’ll jump straight into more real life Node JS concepts like routing and middleware and show how to build front-end clients as well as HTTP services using it.

To be continued… (oh and wish you all a Happy new 2016)!

Tagged ,

Part 6: Custom Components – Tabs

In Part 4 we have seen how to use History.JS along with Crossroads.js to achieve proper client side routing and maintain browser state for proper back button navigation. However, SPAs often have complex page states for example a page with tabbed data or grid data with a particular filter.

One of the ways we can make a particular Tab of data ‘bookmark-able’ is by including the selected tab information as a part of the route. Thus, the particular tab becomes a part of the URL and can be navigated to directly or pushed to the browser history and retrieved on back button.

As you may have noted, our SPA has a name now – SilkThread and a site of it’s own http://silkthread.pw. Today we’ll create a Tab-Item component that will working with SilkThread’s routing mechanism.

Important: When I started this series KO Components was still in Beta, since then version 3.2.0 has gone live and is now available on Nuget also.This article onwards, I am using the release version from Nuget.

Before diving into custom components

We have been using ‘’magic strings” for representing routes, component names and so on. Multi-use components are used more than once, and complex views might be composed of multiple components. Relying on magic strings can be error prone and ‘difficult to maintain’. Why? Well imagine that you have created a component called drop-down in the drop-down folder. Now when you access it elsewhere you specify a magic string ‘drop-down’. But does the next person looking into your code know what it signifies? Is it the component name or the folder name or file name or just a random key? However if you accessed the string via a literal app.components.dropDown.name it will be amply clear that that string is for. So before our framework gets any more complex, let’s take a stab at cleaning up our magic strings.

The Component Registration

We add a new file called app.js in the /app folder. Mind you this is a first stab and we are likely to refactor later. Next we add the following code to it

app = {
components: {
greeter: {
name: ‘greeter’,
template: ‘App/components/greeter/greeting’
}
},
pages: {
home: {
name: ‘home’,
template: ‘App/pages/home/home’
},
settings: {
name: ‘settings’,
template: ‘App/pages/settings/settings’
}
}
}

As we can see this is a simple JS object that splits pages and components into different types and registers each sub object represents a component with two properties name and template to start off with.

Now we update our startup.js to use the appropriate component name and template names.

define([‘jquery’, ‘knockout’, ‘./router’, ‘app’, ‘bootstrap’, ‘knockout-projections’], function ($, ko, router) {
ko.components.register(
app.components.greeter.name, { require: app.components.greeter.template });

    ko.components.register(app.pages.home.name, { require: app.pages.home.template });
ko.components.register(app.pages.settings.name, { require: app.pages.settings.template });
ko.applyBindings({ route: router.currentRoute });
});

Going forward, we’ll register our components via the app.components object.

Registering with Require

We have to tell Require there is a global app object now, so we update the require.config.js and add the app/app route the list.

var require = {
baseUrl: “/”,
paths: {


“app”: “app/app”
    },

}

Getting a little JS help – Including Underscore.js

The Underscore.js library is a very handy toolset and has some nifty helper functions. I’ll explain the ones we use as I use them. To install it, just use the package-management console

PM> install-package underscore.js

The library is by default installed under the Scripts folder. I’ve moved it to the ‘Scripts\underscore’ subfolder.

image

Like the app.js earlier we’ll register Underscore in the require.config.js as well.

var require = {
baseUrl: “/”,
paths: {

“app”: “app/app”,
“underscore”: “Scripts/underscore/underscore”
},

}

With these two modifications to existing code set, we’ll start with the actual component.

Creating a Tab Component

A tab component has two parts, the tabbed header and the panel showing the tab’s content. If we consider the Tab as a menu item it could be a different page altogether. But at any given point a tab control shows only one panel, which is logically related to the selected tab.

To start off with we’ll create a component – tabbed-navigation. The tabbed-navigation component will be the top-level container that will be responsible for showing the tab headers and the selected tab’s container panel. The container panel will be a placeholder div that will be replaced by the component that needs to be shown for the selected tab. We can configure each tab to show a different component.

The tab-navigation HTML template

The HTML template in the app\components\tab-navigation\tab-navigation.html has the following markup:

<ul id=”tabHeader” class=”nav nav-tabs” role=”tablist”>
<!– ko foreach: tabs –>
<li data-bind=”css : {active : isSelected }”>
<a data-bind=”text : text, attr : { href: url }”></a>
</li>
<!– /ko –>
</ul>

<div id=”tabPanel”
data-bind=”component: {name: selected().component, params: {name: selected().text }}”></div>

It has a simple layout using <ul> and the boot-strap styling classes nav and nav-tabs.

Inside the <ul> we loop through an array of tabs items which is going to be encapsulated in the tab-navigation.js view model.

In the loop we add a <li> that has the style active if the viewModel tab’s isSelected property is set to true. This sets the active style from Bootstrap.

In the <li> we have an anchor with two data-bindings. First is the text that’s going to be shown, next the url that’s bound to the href attribute.

Finally we have the <div> tabPanel. This is bound to a component which is initialized with the name and params properties. The name is bound to the selected tab’s component property (so our viewModel has to be able to return a selected tab). In params the only parameter we are currently sending is the name property, which is again picked up from the text property of the selected ViewModel.

The tab-navigation View Model and DataSource

From the above template we can probably guess of a data structure like the following

var ds = {
tabs: [
{
text: ‘selected 0’,
url: ‘/settings/tab0’,
isSelected : true
},
{
text: ‘selected 1’,
url: ‘/settings/tab1’,
isSelected: false
},
{
text: ‘selected 2’,
url: ‘/settings/tab2’,
isSelected: false
}],
selected : function() {
// Return the tab that has isSelected = true;
}
}

To accommodate this structure we use two JS modules – tabsNavigationConfig.js and tabitemConfig.js

tabitemConfig.js

tabitemConfig = function (text, url, selected, component) {
self = this;
self.text = text;
self.url = url;
self.isSelected = selected;
self.component = component;
return self;
}

tabsNavigationConfig.js

tabsNavigationConfig = function (tabitems, selectedIndex) {
self = this;
self.tabs = [];
for (var i = 0; i < tabitems.length ; i++) {
self.tabs.push(tabitems[i]);
if (i == selectedIndex) {
self.tabs[i].isSelected = true;
}
}
return self;
}

The tabsNavigationConfig object has a constructor function that has the list of tabitemConfig objects and the index of which of the tabs is selected.

If you are still wondering as to why we are having a separate datasource for the component, it is simple. We want our component to be re-usable at multiple places, in the same page if required. Hence if we can decouple the data-source from the ViewModel we can configure any number of tab-navigation components with different data-sources. The ViewModel would only be concerned with the rendering and event handling limited to changing of the tabs.

The tab-navigation ViewModel

With the data source ready, we’ll setup the viewModel of the tab-navigation component. I have tagged each relevant line of code with an Index. You can click on them to see more details.

define([“knockout”,
        “underscore”,                                          // #1
“text!./tabbed-navigation.html”],
function (ko, _, tabbedNavigationTemplate) {                   // #2
var isInitialized = false;                                 // #3
var tabsCache = [];
var selectedIndexCache = 0;
function tabbedNavigationViewModel(params) {               // #4
self = this;
if (!isInitialized) {                                  // #5
isInitialized = true;
tabsCache = params.tabConfig().tabs;
}
self.tabs = ko.observableArray(tabsCache);             // #6
self.selectedIndex = ko.observable(selectedIndexCache);// #7
self.selected = ko.pureComputed(function () {          // #8
return self.tabs()[self.selectedIndex()];
}, this);
if (params.route) {                                    // #9
selectByRoute(params.route());
}
function selectByRoute(route) {                       // #10
var newTab = _.find(self.tabs(), function (tab) {   // #11
return tab.url == route();
});
if (newTab) {
self.tabs()[self.selectedIndex()].isSelected = false; //#12
var index = self.tabs().indexOf(newTab);      // #13
select(index);                                // #14
}
return item;                                      // #15
};
function select(index)                                // #16
{
selectedIndexCache = index;
self.tabs()[index].isSelected = true;
self.selectedIndex(index);
}
  return self;
};
return {
viewModel: tabbedNavigationViewModel,
template: tabbedNavigationTemplate };
});

#1: We start off by declaring that we refer to Underscore.js.
#2: Underscore is assigned to the variable _ Winking smile.

#3: We create three cache variables that are a part of the module rather than the viewModel constructor function. These are the list of tabs, the selected index and a flag indicating whether we have some cached information or not. When navigating to a tab we will get routed via the settings route. This will reinitialize the viewModel, so if we have the values cached we can use them instead of initializing the tabbed control everytime.

#4: The viewModel constructor function tabbedNavigationViewModel which takes in an initialization parameter, and may have a tabsConfig property. The tabsConfig has an array of tabs and the index of the selctedTab.

#5: We check if the module is being initialized the first time around. If so, we set the incoming tabs collection into the cache and mark the module as initialized.

#6: We initialize the tabs with the list in tabs cache.

#7: We set the default selectedIndex to 0.

#8: Pure Computed Observables: We have a new type of Observable introduced in KO 3.2.0 called the pureComputed. We know KO had computed observables that automatically updated themselves when their constituent observables changed. However, they suffered from one drawback. Computed observables were always triggered as soon as the constituent observables changed, even if the computed observable was not bound to a view element. This was a performance hit. To resolve this we now have pureComputed observables that get re-calculated only if they have subscriptions, i.e. someone is waiting to update itself based on changes in the pureComputed.

Here we have declared the selected property as a pureComputed and it returns the selected Tab. The selection changes whenever the selectedIndex changes. So anytime the selectedIndex changes the selected property returns the newly selected tab. As we will see in a bit, this renders a new container.

#9: We check if this viewModel is being created as a result of navigation (all cases except of first time page load). If it is due to navigation the route parameter is populated and we use it to select the particular sub-tab indicated by the route property.

#10: The selectByRoute function, called everytime the route changes.

#11: We use the Underscore library to find tab in the tabs collection. The syntax of _.find expects the array of items to look into and a comparison function to call for each element in the array. It returns the first element it finds.

#12: Once we’ve found the element we use the current selected index to set the isSelected flag to false for the current tab.

#13: We retrieve the index of the new selcted tab

#14: Next we call the select method.

#15: The select method sets the isSelected property of the new tab and updates the selectedIndexCache value for future use.

Initializing the Tab Component

Now that we’ve seen the structure of data we need and how that data is used lets see how we can use them. The Tab component is used inside the Settings Page component. So someone has to initialize it in the Settings page.

Tab Component markup in Settings.html

The markup to use the Tab Component is simple and unremarkable:

<div>
<h1>Settings</h1>
</div>
<tabbed-navigation params=”tabConfig : tabbedNavigation(), route: route()”>
</tabbed-navigation>

There are two items being passed in the params property, tabConfig and route. The tabConfig property has the initialization parameters of how many tabs, their text, their URL and so forth. Refer to the tabNavigation viewModel section above.

The binding parameters imply that the Component View Model that’s backing this HTML has to provide he tabbedNavigation and route properties.

Tab Component viewModel code

Before now, the settings component was HTML only. We introduce the backing JS for this component. The code for it is as follows:

define(
[
“knockout”,
“text!./settings.html”,
“underscore”,
“../../components/models/tabbed-navigation/tabsNavigationConfig”,
“../../components/models/tabbed-navigation/tabitemConfig”
],
function (ko, settingsTemplate, _) {
var isInitialized = false;
var tabsNavigationInstance = null;
function settingsViewModel(params) {
var self = this;
self.tabbedNavigation = new ko.observable();
if (!isInitialized) {
isInitialized = true;
tabsNavigationInstance = init(params);
}
self.tabbedNavigation(tabsNavigationInstance);
self.route = new ko.observable();
if (params.tab) {
self.route(params.request_);
}
return self;
};
function init(params) {
var newTabs = [];
for (var i = 0; i < 5; i++) {
var key = ‘tab’ + i;
newTabs.push(new tabitemConfig(
“Settings ” + i,
“/settings/” + key,
key == params.tab,
‘greeter’));
}
tabsNavigationInstance = new tabsNavigationConfig(newTabs, 0);
return tabsNavigationInstance;
}
return { viewModel: settingsViewModel, template: settingsTemplate };
});

The crux of the component view model is the init method that’s called from the constructor function first time around. It need not be called init though. This function initializes an array and pushes in 5 instances of the tabitemConfig that we defined earlier. Since this is a demo we are simply doing a loop. For a real life scenario we would instantiate each instance with a relevant name and more importantly route to a component that should be visible when the tab is selected. In our case we are setting each route to point to the previously created ‘greeter’ component. So for every tab selection we’ll show a greeter component and if you refer back to the original markup at the top you’ll see we pass the selected tabs’ text property to the greeter as a parameter. So the greeter shows name of the tab selected.

Demo time

If we run the application and navigate to the Settings page we’ll see the following

– First tab ‘Settings 0’ is selected
– Greeter is saying Hello to ‘Settings 0’

image

– Clicking on Settings 1 tab, ‘navigates to that tab.Notice the route changes to settings/tab1. This corresponds to the route we setup when initializing the tabitemConfig object.

image

Now we can click on the Browser back button to navigate back to Settings 0 tab, and go forward again to come back to Settings 1 tab. When you navigate you’ll notice that the timestamp of Greeter component keeps changing this is because the greeter component doesn’t cache the time stamp so everytime the constructor function is called, the time gets updated.

Code for this version is available on the Part6 branch of the repository https://github.com/sumitkm/BuildingSpaUsingKO/tree/Part6

Conclusion

In conclusion we saw how we could create a ‘tab-component’ using KO’s component model of development. Next we’ll see how we can use different components in different tabs and how to call server to get/put data.

Tagged , , , ,

Building SilkThread.pw using NancyFX

Background

Those who have been following my Knockout Component series of articles will know I am attempting to build a little SPA framework of my own here. No, it’s not the next best thing since sliced bread, just my attempts at learning Javascript, TypeScript and putting together a bunch of really cool libraries.

To try the entire thing online I decided to purchase a domain and the cheapest one was a .pw. SilkThread sounded like a nice name for a framework that was aiming to string together a series of well written libraries. So here we go, I am going to document my steps on creation of the first cut of http://SilkThread.pw, powered by Nancy and SilkThread itself Smile.

Who Nancy?

Well, it’s not a who, but a What. Nancy FX is an Open Source Web Framework in .Net. Conceptualized and initially built by Andreas Håkansson and supported by an awesome community of .NET devs, it’s now 3+ years old (here’s the list of the contributors). It is inspired by Sinatra in the Ruby world, but I don’t know enough about Sinatra to talk more about the history. It’s primary goal was to help build HTTP services in .NET. However, Nancy is more, it can serve up static content, html and even supports multiple view engines. So its like the best of both AspNET MVC and Web API worlds in one neat bundle.

Why NancyFX instead of AspNet MVC?

Well, no reasons really! Since my SPA effort is aimed at learning stuff and all of it is Open Source, I decided to try an Open Source framework that’s contemporary to the Asp.NET MVC!

My only requirement was that it should be host-able on IIS via my shared hosting provider. Once my Twitter pals Phillip Haydon and Filip Ekberg confirmed this is possible, I was all set to give it a go. I should also mention the gentle nudges from Phillip and Jonathan Channon to try out NancyFX contributed handsomely too Smile.

So no ‘political’ reasons, just an eager beaver trying out a new framework. You have already seen how to do everything I do here using ASP.NET MVC.

Getting Started

Nancy has some neat Visual Studio project templates, so you can get started directly using these templates. But that’s less of fun than learning things ground up. So I decided to start with an Empty Web template.

imageimage

On clicking Ok, a new empty project is created, however we’ll see it has got a bunch of dependencies that I don’t think are required.

image

So we remove the ones shown selected above.

Next we add two Nancy packages from Nuget. If you are using Package Manager console you can get them using the following commands:

PM> install-package Nancy

PM> install-package Nancy.Hosting.AspNet

These two packages are all you need to get started.

A quick “Hello Nancy”

The Nancy equivalent of a ‘’AspNET MVC/WebAPI Controller” is the NancyModule. I have created a Modules folder and created added a HomeModule class in it. The Modules folder will hold our controller layer. In the root, I’ve added a IndexPage.html

image

Next I’ve updated the HomeModule to inherit from Nancy.Module.

In the constructor I’ve added a root path and assigned a method that returns a ViewRenderer. We’ve passed the IndexPage.html to the ViewRenderer because we don’t want any sever side processing done and want to show the HTML as is.

public class HomeModule : Nancy.NancyModule
{
public HomeModule()
{
Get[“/”] = GetIndex;
}

    private dynamic GetIndex(dynamic arg)
{
return View[@”/IndexPage.html”];
}
}

The IndexPage.Html simply says “Hello Nancy”.

<!DOCTYPE html>
<html xmlns=”
http://www.w3.org/1999/xhtml”>
<head>
<title></title>
</head>
<body>
Hello Nancy
</body>
</html>

With that set up, hit F5 and you should have a vanilla page on your default Browser as follows:

image

Well then, the myth of OSS projects being complex to get started with, stands BUSTED! Yes, Nancy is truly a low ceremony, awesome web framework.

But this is not what we want to setup do we? We want a nice Bootstrap Styled SPA! Well, let’s get to work.

Getting SilkThread into the project

To get SilkThread into the project, the best way would have been to get it via Nuget. But creating a Nuget package is a separate post, so we’ll use the age old technique of ‘copy-paste’. I have the latest code from the main branch of the project from Github. So I copied the App and Scripts folder into the project and re-arranged them a little. My new project structure is as follows:

image

I have made the following changes

  1. Created a Views folder and moved the Index.html to it.
  2. Created a Scripts/libs folder and moved all folders previous under Scripts to Scripts/libs
  3. Created a Scripts/app folder and moved the contents of the previous /App to Scripts/app
  4. The above folder realignment requires us to modify the Scripts/app/boot/require.config.js and change it as followsvar require = {
    baseUrl: “/
    Scripts/“,
    paths: {
    “bootstrap”: “libs/bootstrap/bootstrap”,
    “historyjs”: “libs/history/native.history”,
    “crossroads”: “libs/crossroads/crossroads”,
    “jquery”: “libs/jquery/jquery-1.9.0″,
    “knockout”: “libs/knockout/knockout-3.2.0beta.debug”,
    “knockout-projections”: “libs/knockout/knockout-projections.min”,
    “signals”: “libs/crossroads/signals”,
    //”hasher”: “Scripts/crossroads/hasher”,
    “text”: “libs/require/text”
    },
    shim: {
    “bootstrap”: {
    deps: [“jquery”]
    }
    }
    }
  5. Next, install the bootstrap nuget package and removed the scripts folder as we already have the scripts in the libs folder.
  6. Finally we update the GetIndex method in the HomeModule to point to the Views/Index.htmlprivate dynamic GetIndex(dynamic arg)
    {
    return View[@”
    Views/Index.html”];
    }

Now if we run the project we’ll get the following:

super-500-page-by-nancy

The ‘Oatmeal’ has greeted us! Nancy tries hard to tell us what happened and it seems it looked at lots of places but couldn’t find a file. Fear not, it’s a small detail but it’s a safe default.

Explicitly specifying content folders

Basically Nancy serves static content off the Content folder only by default (html files are served from any folder as long as you’ve got the routing right). So when our Index page is trying to access the Scripts folder, things are falling over. To use a custom folder structure like we defined above there are two options a. We move Scripts folder under Content and roll with it OR b. we tell Nancy about our folder structure. Let’s try the second option, it’s rather easy to do so.

  1. Add a new class called SilkThreadBootstrapper and inherit if from Nancy.DefaultNancyBootstrapper
  2. Override the method ConfigureConventions method and use the StaticContentConventionBuilder helper to add folders that you want Nancy to track.
  3. The full code is as follows, as you can see I’ve added the Scripts folder and the Views folderpublic class SilkThreadBootstrapper : Nancy.DefaultNancyBootstrapper
    {
    protected override void ConfigureConventions(
    Nancy.Conventions.NancyConventions nancyConventions)
    {
    base.ConfigureConventions(nancyConventions);
            nancyConventions.StaticContentsConventions.Add(
    Nancy.Conventions.StaticContentConventionBuilder.AddDirectory(“Scripts”));

        }
    }

With those changes done, if we fire up our app, it will come up smoothly.

image

Sweet!

Deploying to the hosting Site

My host doesn’t support a fancy “Deploy from Github on commit to master’’ functionality. So I did it the amateur way:

  1. Got the IIS Web Publishing settings from my host
  2. Imported them into the project.
    Tear hair out because Web Publish keeps giving a weird error. Either provider or Visual Studio is broken.
  3. Enable ftp upload
  4. Setup ftp Deploy and Publish

Here you go! http://silkthread.pw

image

(Note: I will be updating the site to be a little more useful so expect it to change over time).

If you look at the deployment folder it’s got only three dlls, with the total deployment size < 1MB. That’s pretty cool!

image

Conclusion

Nancy FX is a neat little framework with a tiny footprint for quick dash web projects. However, I have not even skimmed the surface of it’s abilities. To try out more I’ll continue to build SilkThread’s site using Nancy. So there will now be two streams of articles in parallel! One, features in SilkThread and the other about updates to the Site using Nancy.

Special Thanks to Phillip Haydon, for proofing the Nancy bits and pointing out some gotchas I comitted as a nOOb.

Source Code

The source code for SilkThread.pw is going to reside at Github, I’ll try to branch it as I go!

https://github.com/sumitkm/silkthreadspa

Tagged , , , ,

QuickBytes: Decimal to Indian Numeric formatting

image

Recently I came across the need to format Decimal as Currency, but force it down to Indian/Vedic/South Asian numeric formatting (thousands, lacs, crores etc.) instead of the standard Arabic/Metric system (thousands, hundred thousands, million, billion etc.).

The answer was easily found in this StackOverflow thread. The code snippet is reproduced here:

string fare = “123000.0000”;
decimal parsed = decimal.Parse(fare,
CultureInfo.InvariantCulture);
CultureInfo hindi = new CultureInfo(“hi-IN”);
string text = string.Format(hindi, “{0:c}”, parsed);

The above code gives us the following string

₹ 1,23,000.00

However, the next requirement was to keep the decimals and formatting but remove the Currency symbol. Another quick search gave us this little gem from Jon Skeet on StackOverflow. Essentially he extracted the NumberFormatInfo from the CultureInfo and reset the Currency Symbol to an empty string. Then use the NumberFormatInfo instance to format the decimal value. So the above code can be modified as follows:

string fare = “123000.0000”;
decimal parsed = decimal.Parse(fare,
    CultureInfo.InvariantCulture);
CultureInfo hindi = new CultureInfo(“hi-IN”);
NumberFormatInfo hindiNFO =
    (NumberFormatInfo)hindi.NumberFormat.Clone();
hindiNFO.CurrencySymbol = string.Empty;

string text = string.Format(hindiNFO, “{0:c}”, parsed);

This gives us the following string. It’s difficult to see here but there is a leading space that you might want to trim if you need to.

1,23,000.00

A Sample Application

I thought it would be a fun project to write some code that gives you the above code for any Culture Code you want, so I setup a basic ASP.NET project and deployed it for free on the AzureWebsites. You can see it in action here – Currency Formatter on Azure WebSites

  • I spun up Visual Studio 2013 and setup a default MVC project.
  • Next I updated KnockoutJS to the latest version

PM> update-package KnockoutJS

  • Added an Entity to encapsulate the culture information. I referred to this list on MSDN as my source.

public class IsoCultureInfo
{
    public int Id { get; set; }
    public string LanguageCultureName { get; set; }
    public string DisplayName { get; set; }
    public string CultureCode { get; set; }
    public string ISO639xValue { get; set; }
}

  • Scaffolded up an EntityFramwork controller: CultureInfoController
  • Added two methods to the CultureInfoController that return JsonResults
  • The first one simply returns the entire list of IsoCultureInfo objects in the DB

public JsonResult List()
{
    return Json(db.IsoCultureInfoes.ToList(), JsonRequestBehavior.AllowGet);
}

  • The second one formats the predefined text based on the incoming Culture Name and returns the formatted text as a JSON object.

public JsonResult FormattedText(string id)
{
     try
     {
         string fare = "123000.0000";
         decimal parsed = decimal.Parse(fare, CultureInfo.InvariantCulture);
         CultureInfo cultureInfo = new CultureInfo(id);
         NumberFormatInfo cultureNFO = (NumberFormatInfo)
cultureInfo.NumberFormat.Clone();
         //cultureNFO.CurrencySymbol = string.Empty;
         string text = string.Format(cultureNFO, "{0:c}", parsed);
         return Json(new { formattedCurrency = text });
      }
      catch (Exception ex)
      {
          return Json(new { formattedCurrency = "N/A" });
      }
}

  • Both these methods are invoked from the Index HTML. The UI is databound to a Knockout ViewModel. This is defined in the script formatCurrency.js

/// <reference path="_references.js" />

var isoCultureInfo = {
    LanguageCultureName : ko.observable(“”)
};

var viewModel = {
    dataList: ko.observableArray([]),
    formattedString: ko.observable(“Test”),
    selectedCulture: ko.observable(isoCultureInfo)
};

$(document).ready(function () {
    $.ajax(“/CultureInfo/List”,
        {
            type: “GET”,
            contentType: “text/json”
        }).done(function (data) {
            viewModel.dataList = ko.mapping.fromJS(data);
            ko.applyBindings(viewModel);

            viewModel.selectedCulture.subscribe(function(newValue){
                if (newValue.LanguageCultureName() != ”) {
                    var data = { “id”: newValue.LanguageCultureName() };
                    $.ajax(“/CultureInfo/FormattedText”,
                        {
                            type: “POST”,
                            contentType: “application/json”,
                            data: JSON.stringify(data)
                        }).done(function (data) {
                            viewModel.formattedString(data.formattedCurrency);
                        }).error(function (args) {
                            alert(“”);
                        });;
                };
            });
        }).error(function () {

        });
});

  • Finally I updated the Index.cshtml of the Home Controller to show the dropdown with the list of culture info.

        Select Culture: <select id="cultureOptions"
                                class="form-control"
                                data-bind="options: dataList(), optionsText: 'LanguageCultureName', value: selectedCulture, optionsCaption: 'Choose...'"></select>

  • Added a <ul> to show all the property values of the selected Culture

<ul>
    <li>Language Culture Name: <b><span data-bind="text: LanguageCultureName"></span></b></li>
    <li>Display Name: <b><span data-bind="text: DisplayName"></span></b></li>
    <li>Culture Code: <b><span data-bind="text: CultureCode"></span></b></li>
    <li>ISO 639x Value: <b><span data-bind="text: ISO639xValue"></span></b></li>
</ul>

  • Next we have a <pre> section which contains the code that changes as per the selected Culture.

<pre>
string fare = “123000.0000”;
decimal parsed = decimal.Parse(fare, CultureInfo.InvariantCulture);
CultureInfo cultureInfo = new CultureInfo(<b><span id=”currentCulture” data-bind=”text: LanguageCultureName”></span></b>);
NumberFormatInfo cultureNFO = (NumberFormatInfo)cultureInfo.NumberFormat.Clone();
// If you don’t want the CurrencySymbol, uncomment the following line
// cultureNFO.CurrencySymbol = string.Empty;
string text = string.Format(cultureNFO, “{0:c}”, parsed);
</pre>

  • Finally we have a span to show the formatted string returned after we have selected the Culture Info

Formatted String: <b><span data-bind="text: $parent.formattedString"></span></b>

Conclusion

The code snippet changes as you select the Culture Info in the dropdown and you can copy paste it directly. I deployed it on a free Azure Website, how? That’s for another day Smile.

Tagged , ,

Developing Windows 8 apps on Windows 8.1 Dev Machine (Updated)

TLDR; Don’t do it

I built Kalliope media player for Windows 8.1 before Windows 8 because the MediaElement and overall APIs that I wanted looked more mature in 8.1 than 8.0 and hence it was ‘faster’ to build it for 8.1.

But Windows 8 PCs still outnumber Windows 8.1 PC by almost 2:1. Lesson for Microsoft, their PC customers are not as keep ‘upgraders’ as say Phone customer (specifically Apple iPhone customers). Anyway, Windows 8 platform was hard to ignore so I decided to backport Kalliope to run on Windows 8.

My Dev Environment

Window 8.1 VM fully patched with Visual Studio 2012 Express and Visual Studio 2013 Express for Windows.

So near yet so far

I was using VS2012 on the VM for the Windows 8 port. Work was almost done, and I was ready to start WACKing the app, when I thought, might as well run it on a Windows 8 machine and test! BAM!!! The Application failed to even navigate properly. Couple of exceptions I’ve caught so far

App_UnhandledException: The property ‘HeaderTemplate’ was not found in Type ‘Windows.UI.Xaml.Controls.Combobox’

App_UnhandledException: Failed to create a ‘Windows.UI.Xaml.TextWrapping’ from the text ‘WrapWholeWords’.

After getting these two, I stopped testing and now restoring my Windows 8 Dev VM so that I can actually build the entire Code on Windows 8 and see what actually compiles and what doesn’t.

Why is this happening?

Well first of course it is because I copy pasted XAML from my Win 8.1 app to my Win 8 app. But then question is shouldn’t it be causing build errors? Well, I think so. I’ll know soon enough once I compile the code in Win 8. But the point is, this exact XAML works in Windows 8.1, in the sense when I hit F5 in VS2012, the app complies without error or warning and runs perfectly fine. Which basically means Windows 8.1 WinRT APIs are more forgiving of XAML errors. However, unfortunately for you, this means you CANNOT trust a Windows 8 build of your app created on a Windows 8.1 machine. Yes Yes Yes, I know… I feel like saying it too… but heck… what’s the point!

Essentially there are API leaks (this is my term, maybe it should be called something else, sue me), because of which Windows 8 apps when run on Windows 8.1 will work even with incorrect XAML attributes (or attributes that were not supported in 8.0 but are supported in 8.1).

Update 1 (Feb 9, 2014)

Well, looks like I am not too much of a trouble, so far the only issues reported are as follows:

image

Mind you, these are visible only if the designers are open. The build is otherwise reported as OK. So these will bite your bum at runtime.

Moral of the story?

1. You need a dedicated Windows 8 machine to develop and test a Windows 8 app, don’t depend on a Windows 8.1 machine.

2. Microsoft has more or less abandoned 8.0 from an API stand point, should you really bother about a back-port? Well you decide!

3. (Updated on Feb 9, 2014) You will not face these issues if you are upgrading your App from Windows 8 to Windows 8.1. You have to be careful only when you backport, so as to not use new stuff (which is understandable). So the only thing is play closer attention to Designer errors.

Conclusion

I may have been a little too harsh on MS, but still it’s clear that there is only one XAML engine in Windows 8.1, the one that has all the enhancements for 8.1. So if you mistakenly put some new stuff in Windows 8 App, it will work on 8.1 but fail in Windows 8.

Tagged , ,
%d bloggers like this: