Monday 6 July 2015

Nativescript - Making the http request module into a re-usable generic function

I am currently working my way through developing a nativescript app. Developed by Telerik, it allows generation of native cross platform applications using Typescript or javascript. I am a fan of Typescript so I will be posting examples in that.

To be able to access JSON from a web server, there is the http module. I wanted to write my own helper class to simplify this down and make it more reusable.

The commonreferences section can be ignored, this is a helper module I use to store server names and particular urls. You could replace this with your server name.

If the call fails, it displays the details in a dialog box for debugging.

import http = require("http");
import commonReferences = require("../res/data/commonreferences");
var commonReferencesData: commonReferences.CommonReferences = commonReferences.data;
import dialogs = require("ui/dialogs");

export function request<T1, T2>(serviceName: string, content: T1, success: (result: T2) => void) {
    var request = JSON.stringify(content), url = commonReferencesData.BaseSiteUrl + commonReferencesData.ExerciseService + serviceName;
    http.request({
        url: url,
        method: "POST",
        headers: { "Content-Type": "application/json" },
        content: request
    }).then(function (response) {
        if (response.statusCode == 500) {
            dialogs.alert("Service : " + url + "\n\nParameters : " + request + "\n\nResponse : " + response.statusCode + ":" + response.content);
        }
        else {
            success(<T2> response.content.toJSON().d);
        }
    });
}


This can be called, as per the example below. As can be seen, you can define the expected input and output types.

import applicationSettingsHelper = require("../../helpers/applicationsettingshelper");
import textHelper = require("../../helpers/texthelper");
import pages = require("ui/page");
import observableHelper = require("../../helpers/observablehelper");
import httpHelper = require("../../helpers/httphelper");
import dialogHelper = require("../../dialogs/dialog/dialog-view-model");

export interface ForgotCallbackResult { userEmail: string }
export interface ForgotCallback { (result : ForgotCallbackResult, success: boolean): void };

export function display(page: pages.Page, action: ForgotCallback) {
    page.showModal("./dialogs/forgot/forgot-page", page, action);
}

export enum fields { userEmail };

interface ForgotUsernameOrPasswordRequest {
    userEmail: string;
    lang: string;
}

export class ForgotModel extends observableHelper.PopupModel<forgotcallbackresult> {
    constructor() {
        super(fields);

        this.addFields([
            {
                fieldName: fields.userEmail,
                validator: new textHelper.TextLengthValidation(applicationSettingsHelper.getUserEmail(), 1, 50, this.languageData.ForgotEmailBlank, this.languageData.ForgotEmailInvalid, "", "")
            }]);
    }

    public returnTrue() {

        this.setLoading(true);
        var forgotUsernameOrPasswordRequest: ForgotUsernameOrPasswordRequest = { userEmail: this.getValue(fields.userEmail), lang: applicationSettingsHelper.getLanguage() };
        httpHelper.request<forgotusernameorpasswordrequest,string>("/ForgotUsernameOrPassword", forgotUsernameOrPasswordRequest,(result: string) => {
            dialogHelper.displayInformation(this.page, result);
            this.returnValue = {
                userEmail: this.getValue(fields.userEmail)
            };

            this.returnResult(this.returnValue, true);
            this.setLoading(false);
        });

    }
}

export var forgotViewModel = new ForgotModel();


I will talk next about making better dialog boxes.

Nativescript - Making your own bulleted or numbered list

I am currently working my way through developing a nativescript app. Developed by Telerik, it allows generation of native cross platform applications using Typescript or javascript. I am a fan of Typescript so I will be posting examples in that.

I wanted to be able to display bulleted or numbered lists in my views. Views are developed using xml. To do this, I developed a custom component that uses labels inside a grid layout.

The first step was to make a texthelper class. You can refer to this class file in the xml layout.

You can then add your own custom components like below.


  
    
      
      
    
      
        
    
  


The typescript is quite simple and can be seen below.

// Makes a bulleted or numbered list using a grid layout
// Accepts a string value and a seperator

export function makeList(gridLayoutAdd: gridLayout.GridLayout, stringValue: string, seperator: string, bullet: boolean): void {
    var stringValues = stringValue.split(seperator);

    makeListFromArray(gridLayoutAdd, stringValues, bullet);
}

// Makes a bulleted or numbered list using a grid layout
// Accepts a string array and a seperator

export function makeListFromArray(gridLayoutAdd: gridLayout.GridLayout, stringValues: Array, bullet: boolean): void {
    try {
        gridLayoutAdd.addColumn(new gridLayout.ItemSpec(30, gridLayout.GridUnitType.pixel));
        gridLayoutAdd.addColumn(new gridLayout.ItemSpec(1, gridLayout.GridUnitType.star));

        for (var i = 0, imax = stringValues.length; i < imax; i++) {
            var labelAdd = new label.Label();
            labelAdd.text = stringValues[i].trim();
            gridLayout.GridLayout.setRow(labelAdd, i);
            gridLayout.GridLayout.setColumn(labelAdd, 1);
            labelAdd.textWrap = true;
            gridLayoutAdd.addChild(labelAdd);

            labelAdd = new label.Label();
            if (bullet) {
                labelAdd.text = "-";
            }
            else {
                labelAdd.text = (i + 1) + ")";
            }
            gridLayout.GridLayout.setRow(labelAdd, i);
            gridLayout.GridLayout.setColumn(labelAdd, 0);
            labelAdd.textWrap = true;
            labelAdd.style.verticalAlignment = "top";
            gridLayoutAdd.addChild(labelAdd);

            gridLayoutAdd.addRow(new gridLayout.ItemSpec(1, gridLayout.GridUnitType.auto));
        }
    }
    catch (ex) {
        dialogs.alert(ex.message);
    }

}

// Used for building a bulleted list from a string seperated by a key

export class BulletedList extends gridLayout.GridLayout {

    private _seperator: string = "#";
    private _stringValue: string;
    constructor() {
        super();

    }

    // Seperator to split lines of text

    public get seperator(): string {
        return this._seperator;
    }

    public set seperator(value: string) {
        this._seperator = value;
    }

    // String value to split into lines of text

    public get stringValue(): string {
        return this._stringValue;
    }

    public set stringValue(value: string) {
        makeList(this, value, this.seperator, true);
        this.stringValue = value;
    }

}

// Used for building a number list from a string seperated by a key

export class NumberedList extends BulletedList {


    // String value to split into lines of text

    public set stringValue(value: string) {
      
        makeList(this, value, this.seperator, false);
        this.stringValue = value;
    }


Hopefully you will find this useful, I will post other examples.