Showing posts with label Knockout. Show all posts
Showing posts with label Knockout. Show all posts

Saturday, September 8, 2012

Staring at boobs gave me an idea for Underscored Knockout

I have been using knockout.js ever since I discovered it. Since that time also, my JavaScript chops have been getting good to the point I discovered (and using) underscore.js. Let's face it, array and/or collections handling in plain JavaScript isn't pretty.

Then a couple of days ago, I was staring that this random lady's cleavage on the ride to work - had my sunglasses so she was none the wiser - that I suddenly had a great idea - Knockout's arrays with Underscore's array functionality. And I was like, "FUCK! Why did I think of this sooner?!" Needless to say, I forgot about the boobies.

When I got to work, I fired up my browser and searched the web if someone got the same idea thankfully, Kamran Ayub thought about it while driving home from work - UnderscoreKO. It's was exactly what I was thinking! If I had discovered underscore sooner, I bet I would have wrote this beauty of a library.  Now I can stop writing half-ass functions/closures of my design to merge arrays or search it for certain values and get to writing short, concise, functional Knockout code.

Thank you Kamran!


Tuesday, August 21, 2012

My CodeIgniter + Bootstrap starter kit


I thought I would share my CodeIgniter + Bootstrap starter kit.

Highlights:
- CodeIgniter 2.1.0 codebase included
- Bootstrap 2.0.3 theme with its JS extensions in a single file
- jquery 1.7.1 and knockout 2.1 included
- default controller: home/start.php; default view: home/start.php

To use, it just drop inside your /htdoc or /var/www folder.

Download the zipped file or clone it from my bitbucket mercurial repo. To clone:

hg clone https://bitbucket.org/jaypax/cibootstrap

Have fun with it.

Updated 9/29/2012

  • Updated Bootstrap to 2.1.0 
  • Added bootstrap-responsive.css (min version included)
  • Updated CodeIgniter to 2.1.2 
  • Added underscore.js 
  • Added underscore-ko.min.js (see https://github.com/kamranayub/UnderscoreKO) 
  • Added jquery-1.7.1-vsdoc.js

Wednesday, April 18, 2012

Getting knocked around while dealing with a check box

I've been using Knockoutjs heavily these couple of weeks and I think it has place in my programming toolkit. With Knockout, my markup is significantly cleaner and my pages with form elements are not a pain.

Knockout isn't that hard to use. I bet you can get a good handle of it once you finish some of the tutorials. Knockout, also has a couple of cool extensions like combining it with Kendo. I got good with Knockout but I had stuff to learn.

I had to implement a feature where an "admin" can select a "role" for new accounts. To select a role, admin had to select one of three check boxes in the page. The data for the check boxes is from JSON. Not a big problem since Knockout plays nice with jQuery.

So what exactly is the problem then?

The problem was that I needed to capture the "checked" value and push it into a new array. You would think that this a straight-forward preposition. So my first attempt went something like:

My Knockout script
<script type="text/javascript"> 
...{some code omitted for clarity}
        function roleModel(id, name, description) {
            var self = this;
            self.RoleId = id;
            self.RoleName = name;
            self.Description = description;
        }

        function viewModel(){
            var self = this;
            self.AvailableRoles = ko.observableArray();
            $.getJSON("/Role/GetRoles", function (data) {
                for (var i = 0; i < data.length; i++) {
                    self.AvailableRoles.push(new roleModel(data[i].RoleId, data[i].RoleName, data[i].Description));
                }
            });
            self.Roles = ko.observableArray();
        }
...{some code omitted for clarity}

        ko.applyBindings(new viewModel());

My Markup (HTML5)
<div data-bind="foreach: AvailableRoles">  
    <input type="checkbox" data-bind="attr: {value: AvailableRoles}, checked: Roles"/>  
    <span data-bind="text: RoleName"></span>  
</div>  
Notice the Roles and AvailableRoles properties. Apparently you can't bind the AvailbleRoles "directly" into the value field of the checkbox.

After looking around the web, I hit on the that idea I needed an intermediary field to store a key (thus I can bind it into the checkbox's value field) then I can use that key to retrieve the right role object from the AvailableRole object which is an array of role objects and store it in the Role property.
            
            self.Roles = ko.computed(function () {
                return ko.utils.arrayMap(self.SelectedRolesIds(), function (roleId) {
                    return ko.utils.arrayFirst(self.AvailableRoles(), function (item) {
                        return item.RoleId == roleId;
                    });
                });
            });
            self.SelectedRolesIds = ko.observableArray();
That's the SelectedRolesIds property in my viewModel. I also changed the Roles propety to be a computed field to make it "dependent" on what Role Ids are present in the SelectedRolesIds property. You still have to make changes to the markup. This all made nice with knockout utility functions - arrayMap and arrayFirst.

<div data-bind="foreach: AvailableRoles">  
    <input type="checkbox" data-bind="attr: {value: RoleId}, checked:$root.SelectedRolesIds"/>  
    <span data-bind="text: RoleName"></span>  
 </div>
The AvailableRoles property stays the same.