Binding String and Number to Angular Checkbox

By default Angular and Material checkboxes bind to boolean properties.

export class MyComponent {
    isActive:boolean = true
}
<input type="checkbox" [(ngModel)]="isActive"/>

<mat-checkbox [(ngModel)]="isActive">Check me</mat-checkbox>

But what if you have string or integer numbers indicating a boolean state. For example, we often use “Y”, “N”, 1 and 0 as boolean indicators in the database. Let’s explore a few ways of doing this.

Using Checked and Change Event Binding

We can separately bind the checked property and the change event for the checkbox.

export class MyComponent {
    strValue: String = "Y"
}
<input type="checkbox" 
  [checked]="strValue === 'Y'" 
  (change)="strValue = $event.target.checked ? 'Y' : 'N'"/>

For Material checkbox the $event variable has a different type. You need to directly access the checked property.

export class MyComponent {
    intValue: number = 1
}
<mat-checkbox 
  [checked]="intValue === 1" 
  (change)="intValue = $event.checked ? 1 : 0">Check me
</mat-checkbox>

Using Property Accessor

Another approach is to define a new property in the component that simply maps the String or number values to boolean using property accessors.

export class MyComponent {
    isActive: number = 1

  get isActiveBool() {
    return this.isActive == 1
  }

  set isActiveBool(newValue:boolean) {
    this.isActive = newValue ? 1 : 0
  }
}

This will define a new property called isActiveBool which is just the isActive property converted to a boolean. Now you can bind this new property to a checkbox.


<input type="checkbox" [(ngModel)]="isActiveBool"/>

<mat-checkbox [(ngModel)]="isActiveBool">Check me</mat-checkbox>

I find this second approach cleaner. It also gives you a chance to do more complex mapping from any data type to boolean.

Advertisements

ReactJS from Scratch

ReactJS ships a tool called create-react-app that can generate a new project for you. This gets one started very quickly. But I see several problems with a generated project:

  1. The build process is heavily abstracted. Meaning, it hides how Webpack and Babel are used and configured.
  2. It launches a web server that uses Websocket to automatically refresh a web page when you modify any code.

These may sound like conveniences rather than problems. But neither will be acceptable in most real life projects. We need to be able to configure Webpack and Babel the we like. Also, most likely we will need to go through a regular web server like Nginx etc.

This is also inconvenient for someone who is new to ReactJS and Webpack. So many things are hidden away from you that you think you are not quite learning how the system operates.

In this article I will create a ReactJS project from scratch. We will use Webpack and Babel. We will learn how to configure them.

Continue reading

Async/Await with Koa

At the time of this writing (July 2017), KoaJS and most of its popular middleware support ES6 async/await. NodeJS had been supporting them for some time as well. Here we will see a minimal example of koa and koa-router packages using async/await.

Install the packages:

npm i koa koa-router --save

Create a JS file as follows.

var Koa = require('koa');
var router = require('koa-router');

var app = new Koa()
var api = router();

api.get('/hello', async (ctx) => {
    ctx.response.body = await f1()
});

app
  .use(api.routes())
  .use(api.allowedMethods());

app.listen(8080);

async function f1() {
    return new Promise((resolve, reject) => {
        let message = {
            greeting: "Hello",
            planet: "World"
        }

        resolve(message)
    })
}

This shows how to use an async method for routing.

Save and run the file.

Then, run curl to test it out.

curl -v localhost:8080/hello

Verify that the response content type is application/json; charset=utf-8 and the body is:

{"greeting":"Hello","planet":"World"}

Controlling Screen Orientation of iOS Apps

By default an iOS app will support all possible orientations (landscape, portrait left, portrait right, etc.). When a user rotates the device the app will automatically rotate to fill the screen. In many cases this may not be a desirable behavior. For example, your app may have been designed for portrait mode only. In more complex cases you may have to support different orientations for different screens of the app. For example, a video player must work in either portrait or landscape mode where as the rest of the app only supports portrait.

The process to control how the app behaves when the screen is rotated can be a bit confusing. This article will shed some light on the issue.

Continue reading

Use JSON Web Token with Koa

JSON Web Token (JWT) is used to issue a secure authentication token once the user successfully logs in. In Koa we use the koa-jwt middleware to manage these tokens.

npm install koa-jwt --save

Import the package from your code.

var jwt = require('koa-jwt');

We can use the middleware to guard access to protected URLs. The following will try to decrypt the token sent with the request using the secret key 'pa$$word'. If that does not succeed the processing pipeline will be terminated and the subsequent middlewares will not run. We use the unless escape hatch so that this token validation is skipped for paths starting with "/public".

app.use(jwt({ secret: 'pa$$word' })
    .unless({ path: [/^\/public/] }));

Add the jwt middleware before any routes for it to have any meaningful effect.

A new token is issued using jwt.sign(). You can store identifying information like user ID, name etc. as a payload in the token.

api.get('/public/login', function *(){
    var user = {
      userId: "bibhas",
      name: "Bibhas B"
    }

    this.body = {
      token: jwt.sign(user, "pa$$word")
    }
});

A client is responsible for saving the token and sending it back with every request using the Authorization header. In the example below ABCXYZ is a token issued by the server:

curl -H "Authorization: Bearer ABCXYZ" localhost:8080/protected-stuff

The middleware saves the payload decrypted from the token as the state.user property of the context. So we can easily access that as follows:

api.get('/protected-stuff', function *(){
    var userId = this.state.user.userId //"bibhas"
    var fullName = this.state.user.name //"Bibhas B"
});