Friday, December 19, 2014

AngularJS - Apply Style to currency and percentage texts before bind to UI

I have a scenario where i need to highlight currency amount values and percentage values within html text. I went over so many sites to achieve this and finally got achieved this using AngularJS with JavaScript.

What i expected is below:



What Steps i done to achive this below:

1: Create Javascript function to replace currency and percentage matched text to our required style. In this case i have used regular expression

var ReplaceCurrencyText = function (text) {
    var returnText = text.replace(/(\$?(?=\(.*\)|[^()]*$)\(?(\d{1,6}|\d{1,3},\d{3})(\.\d\d?)?\)?\%?)/g, "<span style=’color:green;’>$1</span>");
    return returnText;
};


Here $1 represents RegEx matched 1st group. Each brackets considered as one group, but in this case i used only one group (i.e., (\$?(?=\(.*\)|[^()]*$)\(?(\d{1,6}|\d{1,3},\d{3})(\.\d\d?)?\)?\%?) ).

2: Create angular directive which used to replace currency and percentage text as required

angularApp.directive('displayStyledCurrencyValue', ['$sce', function ($sce) {

    return {
        restrict: 'AE',
        replace: true,
        template:
                   '<div ng-bind-html="getStyledHtml(htmlText)"></div>',
        scope: {
            htmlText: '='
        },
        link: function (scope, element, attrs) {
            scope.getStyledHtml = function (html) {
                return $sce.trustAsHtml(ReplaceCurrencyText(html));
            };
        }
    };
}]);

Here i have used ng-bind-html to render text as html so that html element will not be shown as text and for this i used $sce.trustAsHtml method to return as html string. JavaScript function ReplaceCurrencyText called inside angular directive to get my required format of currency amount and percentage text.


3: Call this angular directive in html page wherever required and th

<display-styled-currency-value html-text="someValueToBind"></display-styled-currency-value>

Wednesday, December 10, 2014

MVC - 401 Unauthorization redirect page

Sometimes we need to redirect our pages to some specific path when 401 unauthorized error happen. But by default it will redirect to some predefined path (Ex: ../login.aspx?ReturnUrl=home/index) and it may go 404 error if not found in our project.

To customize this default redirect path, i went through many ways and finally found simple change is

<authentication mode="Forms">
      <forms timeout="60" loginUrl="~/" />

</authentication>

Note: In browser network tab we cannot see 401 (Unauthorized) error, it will show as 302 (Redirect found). To resolve this, we can customize application end request method in global.asax file like below, But it will not redirect to login page instead it will show error page.

void Application_EndRequest(object sender, EventArgs e)
{
    if (Context.Response.StatusCode == 302)
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

Friday, December 5, 2014

AngularJS - Intercept all ajax calls globally

Add following code in app module config section to handle success or error globally.

In below example i have handled 401 unauthorized error globally.

App.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.useXDomain = true;
    $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; //Post
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
    var interceptor = ['$rootScope', '$q', function (scope, $q) {
        function success(response) {
            return response;
        }
        function error(response) {
            var status = response.status;
            console.log("site error: " + status);
            if (status == 401) {
                window.location.href = currentDomain;
                return;
            }
            // otherwise
            return $q.reject(response);
        }
        return function (promise) {
            return promise.then(success, error);
        }
    }];
    $httpProvider.responseInterceptors.push(interceptor);

}]);