Continued from day 1, day 2, day 3.
This lesson was mostly about writing Object Oriented in JavaScript.
Lets start by creating a basic model Customer, customer contains a first name, last name and full name that contains both:
var _this = this;
_this.firstName = 'Yair';
_this.lastName = 'Siwek';
_this.fullName = _this.firstName + ' ' + this.lastName;
}
Given that this is our body:
<div>
<span id="firstName"></span>
--
<span id="lastName"></span>
</div>
<div>
<span id="fullName"></span>
</div>
</body>
A basic use for the model will be:
<script>
$(function () {
var cust = new customer();
cust.firstName = "Moshe";
$('#firstName').html(cust.firstName);
$('#lastName').html(cust.lastName);
$('#fullName').html(cust.fullName);
});
</script>
This works.
But what if before using jQuery we would have changed firstName? then fullName would have still been Yair Siwek. In order for the right value for fullName to appear we need to change fullName to a method:
{
//if we wrote this then it's value would have been fullName, but _this is customer!
return (_this.firstName + ' ' + _this.lastName);
};
TODO: _this
We also need to change our html:
$('#fullName').html(cust.fullName());
to use a method instead of a property.
We can now create another instance of customer:
var cust1 = new customer();
But if we use a debugger we will see the method fullName is recreated for each instance of customer:
To fix that we will use a Prototype. A Prototype is common to all instances:
var _this = this;
_this.firstName = 'Yair';
_this.lastName = 'Siwek';
}
customer.prototype = {
fullName: function ()
{
//_this does not exist here!
return (this.firstName + ' ' + this.lastName);
}
}
Note: We can’t use _this here because it doesn’t exist in the scope.
Now the instance doesn’t include the implementation (the Prototype has it).
We could have also used an Anonymous Type:
$(function () {
var cust = {
firstName: 'Joe',
lastName: 'Sh',
fullName: function () {
return cust.firstName + ' ' + cust.lastName;
}
};
$('#firstName').html(cust.firstName);
$('#lastName').html(cust.lastName);
$('#fullName').html(cust.fullName());
});
</script>
Though we can’t use multiple instances the result is the same.
Book recommendation: Learning JavaScript Design Patterns by Addy Osmani (166 pages)
Shows how to create an empty object – 3 ways.
With the last example there was a problem: changing the values does not change the controls:
$('#firstName').html(cust.firstName);
$('#lastName').html(cust.lastName);
$('#fullName').html(cust.fullName());
cust.lastName = 'Blah';
Both last name and full name won’t contain “Blah”.
To solve that we will have to do a data binding with KnockOut.
cust.firstName = "Moshe";
ko.applyBindings(cust,
//$('#divTop'));//doesn't work
//document.getElementById('divTop'));//works
$('#divTop')[0]);//work
cust.lastName = 'Blah';
model – the data
node - the element on which we want to the binding,
$(‘#Name’) returns an array, node needs a single element so we will have to pass the first element by adding [0].
Note: to add inteliscence to the JavaScript code we will drag and drop the KnockOut library to the top of the script, it will be converted to:
And from now on you have inteliscence turned on (if you have Resharper then you can skip this step).
To make the model observable we will have to change each field to be an observable by:
_this.lastName = ko.observable('Siwek');
that will convert it to a method which is used by:
In HTML:
In JavaScript:
fullName: function ()
{
return (this.firstName() + ' ' + this.lastName());
}
}
When writing the data-bind from the HTML you can use either name() or name. But from JavaScript you must use name().
TODO:check why in JS
TODO: 18:06 not clear: when working with ko.computed +ko.observable than firstName() in the HTML data-bind doesn’t work. TODO: add code
TODO: There is difference between ko.computed and function(), computed is only called once?
Observable Array
When the array is simple (non object):
<li>
<span data-bind="text: $index" ></span>
.
<span data-bind="text: $data" ></span>
</li>
</ul>
$index – the index of the item in the array.
$data – the item data
Output:
When the array is of objects we can bind to the property names:
{ subject: 'hist', mark: 90 },
{ subject: 'math', mark: 95 } ]);
<li>
<span data-bind="text: subject" ></span>
-
<span data-bind="text: mark" ></span>
</li>
</ul>
Note: for intelliscence in KO you will have to install ASP.NET and Web Tools 2012.2.
KO Templates
HTML usage of a Template has at least 2 prameters:
name – the template name
data – the observable data
The template definition:
TODO: Add code
id – the name of the template
Adding templates to a page:
1. Using href:
TODO
Will cause the template to be downloaded to the client even when the template is not used.
2. Dynamically through JS code:
TODO