Sunday, February 24, 2013

Please RTFM

Got my fair share of RTFM last week. I've written a REST-adhering AngularJS code for deletions. I'd written it this way:


$http.delete('/departments', { Id: d.DepartmentId }).success(function (responseData) {
            alert('ok');
});


But the record is not deleted.

I assumed the second parameter is a data parameter, I should thought early that second parameter has many options. Another lesson learned, aside from not reading the AngularJS doc, handling errors should be our second nature, the errors provided by ServiceStack helps a lot for debugging why the particular method for RESTful deletion is not routed to its proper service method.

Upon adding .error callback, lot of guessworks were avoided on why there's a 405 error, which naturally led me to read AngularJS doc. $http delete has a config parameter, the second parameter is not directly a data paramater


To correctly pass the data parameter with AngularJS:

$http.delete('/departments', { params : { Id: d.DepartmentId } }).success(function (responseData) {
    alert('ok');
}).error(function(data, status, headers, config) {
    console.log(data);
    alert(data.ResponseStatus.Message);
    alert(status);
});


Obligatory xkcd reference: http://xkcd.com/293/

Tuesday, February 12, 2013

Got multitude of jQuery approaches to offer? Thanks but no thanks, I got AngularJS

Just when I thought I already unearthed all the possible techniques for obtaining the value from a dropdown selection:

$('#CountryCode').change(function () {


 // Why use this?
 // alert($('option:selected', '#CountryCode').val());

 // Or this?
 // alert($('option:selected', $(this)).val());


 // When this will suffice:
 alert($(this).val());
});



Apparently, I lack imagination, I saw this code from a dropdown change event:

$('#CountryCode > :selected').attr('value');


Something is fundamentally wrong on that last code but I can't quite put my finger on it. Oh darn, now I remember.. that attr('value') is so leaking the abstraction!


Getting the value of something is a staple in our everyday job, hence we should give it a first-class treatment, give it a proper abstraction, i.e. we should be able to use this: $(this).val(), not a hodge-podge of stringly-typed voodoo magic that $('#Country > :selected').attr('value') is


I'm not gonna remember all the possible jQuery combinations the mankind has ever known just to obtain that elusive value from a dropdown control, what other approaches should I remember?


Ok, thanks, but no thanks, I got AngularJS, I just have to remember this: $scope.CountryCode



The question I posed above is rhetorical, but you can probably show other jQuery approaches for getting the value from a dropdown change event that I missed, be it a shorter code or long code, seriously.


Being abstract is something profoundly different from being vague... The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise. -- Edsger Dijkstra

Monday, February 11, 2013

Javascript mental gymnastic

var s = 
     '(function() {\
        return function(n){\
            return n * n;\
        };\
     })()';
     
     
var f = eval(s);
console.log(f);
alert(f(3));

Wednesday, February 6, 2013

Give semantics to your web app using AngularJS

Make percent inputs conform to their true semantics, i.e. 27% is 0.27, just like in Excel. Not the textual 27 which necessitates manually dividing the number by 100 when using it further on expression.



When you input 27 on Interest Rate Per Annum textbox, the model’s returned value should be 0.27. Note the custom attribute percent below. AngularJS can augment your existing HTML and introduce new attributes to them, it can even create new HTML tags. The percent attribute automatically convert the percent input to its percent value.



<input type='text' ng-model='InterestRatePerAnnum' percent/>
  
<input type=’text’ ng-model='TotalContractPrice' />
 
.
.
.

var result = $scope.InterestRatePerAnnum * $scope.TotalContractPrice;


Live code: http://jsfiddle.net/b75xaj69/



Contrast to manual approach:


<input type='text' id='InterestRatePerAnnum' />
 
<input type=’text’ id='TotalContractPrice' />

.
.
.
 
var result = ($('#InterestRatePerAnnum').val() / 100) * $('#TotalContractPrice').val();

Tuesday, February 5, 2013

Binding vs DOM manipulation. AngularJS vs jQuery

Bind JavaScript values (aka JSON) to HTML so incessant element placeholders won’t be needed as much

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="angular.min.js"></script>
</head>

<body ng-app>


<label for="Multiplier">Multiplier</label><input ng-model="Multiplier" type="text"><br/>
<label for="Multiplicand">Multiplier</label><input ng-model="Multiplicand" type="text"><br/>
<input value="Multiply" type="button"/><br/>

<b>Product of {{Multiplier}} and {{Multiplicand}} is {{Multiplier * Multiplicand}}</b>




</body>
</html>


DOM Manipulation, very tedious:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="jquery-1.9.0.min.js"></script>
</head>

<body>


<label for="Multiplier">Multiplier</label><input id="Multiplier" type="text"/><br/>
<label for="Multiplicand">Multiplier</label><input id="Multiplicand" type="text"/><br/>
<input value="Multiply" type="button" id="Multiply"/><br/>

<b>Product of <span id="MultiplierSpan"></span> and <span id="MultiplicandSpan"></span> is <span id="ProductSpan"></span></b>


<script type="text/javascript">

    $(function() {

        $('#Multiplier').keyup(function() {
            var multiplier = $('#Multiplier').val();
            $('#MultiplierSpan').text(multiplier);


            computeProduct();
        });

        $('#Multiplicand').keyup(function() {
            var multiplicand = $('#Multiplicand').val();
            $('#MultiplicandSpan').text(multiplicand);


            computeProduct();
        });


        function computeProduct() {
            var multiplier = $('#Multiplier').val();
            var multiplicand = $('#Multiplicand').val();

            var product = multiplier * multiplicand;
            $('#ProductSpan').text(product);
        }



    });

</script>

</body>
</html>

Sunday, February 3, 2013

jQuery is too imperative, get declarative with AngularJS

Imperative approach is too ceremonial:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="jquery-1.9.0.min.js"></script>
</head>
<body>

Show Favorite Numbers: <input id="ShowFaveNumbers" type="checkbox">

<ul id="FaveNumbers">
    <li>5</li>
    <li>2</li>
    <li>0</li>
</ul>



<script>
    $(function() {

        function showOrHide() {
            var isChecked = $('#ShowFaveNumbers').is(':checked');

            var fn = $('#FaveNumbers');
            if (isChecked)
                fn.show();
            else
                fn.hide();
        }


        $('#ShowFaveNumbers').change(function() {
            showOrHide();
        });

        showOrHide();

    });
</script>


</body>
</html>


Get declarative with AngularJS:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="angular.min.js"></script>

</head>

<body ng-app>

Show Favorite Numbers: <input ng-model="ShowFaveNumbers" type="checkbox">

<ul ng-show="ShowFaveNumbers">
    <li>5</li>
    <li>2</li>
    <li>0</li>
</ul>



</body>
</html>


Live codes:

AngularJS: http://jsfiddle.net/t83UC/

jQuery: http://jsfiddle.net/ZzeuR/

jQuery many rules makes me embrace AngularJS more

Converting jQuery prop method to is method:

var isChecked = $('#ShowFaveNumbers').prop('checked');

Is not a mere changing of the method:

var isChecked = $('#ShowFaveNumbers').is('checked');


You have to remember some rules, must do this:

var isChecked = $('#ShowFaveNumbers').is(':checked');


In AngularJS, it's just a mere getting of model

var isChecked = $scope.ShowFaveNumbers;