when we implement an web app with knockout JS, we encounter an issue in the page load.
we create an observable object to store an object with observable properties.
self.MyObservable=ko.observable();
self.myObject=new MyObject(){
property1: ko.observable(),
property2: ko.observable(),
property3: ko.observable()
}
self.MyObservable(self.myObject);
in the method.. we have the logic to check the property1 value
then we have to access the property1 with the following code
self.MyObservable().property1()
unfortunately we encounter TypeError:property1 is not a function in chrome debugger
here is the work around to fix the error.
if (ko.isObservable(self.MyObservable().property1)) {
return self.MyObservable().property1();
}
a blog to share Microsoft technologies Azure, DotNet, SharePoint, SQL Server,JavaScript Framework: Node.JS, Angular, React
Showing posts with label KnockOut JS. Show all posts
Showing posts with label KnockOut JS. Show all posts
Thursday, June 13, 2019
Monday, June 10, 2019
how to create a Knockout JS custom handler for duplicate email validation?
In the current Knockout JS web application, we want to validate the user input in the email field to make sure the input does not exist in our system.
i implemented the business logic in the textbox blur event. it means that the validation call to the back end when the cursor leaves the textbox.
here is snippet of code to implement binding handler in Knockout JS
ko.bindingHandlers.validateEmail = {
init: function (element, valueAccessor, allBindingsAccessor, data, context) {
var options = allBindingsAccessor().validateEmailParams || {};
$(element).blur(function () {
var customerId = options.customerID();
var email = options.emailAddress();
var value = valueAccessor();
var dataModel = sci.dataModel;
dataModel.CheckDuplicateEmail(customerId, email).then(function (response) {
if (response != null) {
if (response) {
valueAccessor().setError(loc.DuplicateEmailMySubaruAccount);
}
}
});
});
return ko.bindingHandlers.value.init.apply(this, arguments);
},
update: ko.bindingHandlers.value.update
};
HTML Code
<input autocomplete="off" id="email" class="form-control" type="text" data-bind="value: email,validationElement:email, validateEmail:email, validateEmailParams:{emailAddress: email, customerID:accountNumber}, attr: { placeholder: loc.Email }" />
i implemented the business logic in the textbox blur event. it means that the validation call to the back end when the cursor leaves the textbox.
here is snippet of code to implement binding handler in Knockout JS
ko.bindingHandlers.validateEmail = {
init: function (element, valueAccessor, allBindingsAccessor, data, context) {
var options = allBindingsAccessor().validateEmailParams || {};
$(element).blur(function () {
var customerId = options.customerID();
var email = options.emailAddress();
var value = valueAccessor();
var dataModel = sci.dataModel;
dataModel.CheckDuplicateEmail(customerId, email).then(function (response) {
if (response != null) {
if (response) {
valueAccessor().setError(loc.DuplicateEmailMySubaruAccount);
}
}
});
});
return ko.bindingHandlers.value.init.apply(this, arguments);
},
update: ko.bindingHandlers.value.update
};
HTML Code
<input autocomplete="off" id="email" class="form-control" type="text" data-bind="value: email,validationElement:email, validateEmail:email, validateEmailParams:{emailAddress: email, customerID:accountNumber}, attr: { placeholder: loc.Email }" />
Monday, January 8, 2018
how to create a custom binding handler for format phone number input with specific pattern in KnockoutJs web app?
If we want to format the phone number on user input, we can handle it with keypress event using Jquery.
here is sample code to force the user can input 10 number and automatically format them to be
XXX-XXX-XXXX
$("#phoneNumberInput").keypress(function (e) {
if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
return false;
}
var currentChar = this.value.length;
var currentValue = $(this).val();
if (currentChar == 3) {
$(this).val(currentValue + "-");
} else if (currentChar == 7) {
$(this).val(currentValue + "-");
}
$(this).attr('maxlength', '12');
});
in KnockoutJs, we can implement a custom binding handler, then we can apply it to all phone number input fields,
with the keydown event to prevent any non numeric value.
update function in the handler will format the text change to the specific format after user enter 10 nueric values.
ko.bindingHandlers.formatPhoneNumber = {
init: function (element, valueAccessor) {
$(element).on("keydown", function (event) {
if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
(event.keyCode == 65 && event.ctrlKey === true) ||
(event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) ||
(event.keyCode >= 35 && event.keyCode <= 39)) {
return;
}
else {
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
event.preventDefault();
}
}
});
},
update: function (element, valueAccessor) {
$(element).val(ko.unwrap(valueAccessor()));
formatPhone(element);
}
};
formatPhone = function (element) {
var phone= $(element).val().replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
$(element).val(phone);
}
it is very easy to use in the html page. here we will use textInput Binding from KnockoutJs framework to trigger the formatPhoneNumber update method immediately after the user key in 10 numbmers.
<input id="phone" class="form-control" type="text" placeholder="Home Phone" data-bind="textInput: homePhone, formatPhoneNumber:homePhone, validationElement:homePhone " maxlength="10" />
here is sample code to force the user can input 10 number and automatically format them to be
XXX-XXX-XXXX
$("#phoneNumberInput").keypress(function (e) {
if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
return false;
}
var currentChar = this.value.length;
var currentValue = $(this).val();
if (currentChar == 3) {
$(this).val(currentValue + "-");
} else if (currentChar == 7) {
$(this).val(currentValue + "-");
}
$(this).attr('maxlength', '12');
});
in KnockoutJs, we can implement a custom binding handler, then we can apply it to all phone number input fields,
with the keydown event to prevent any non numeric value.
update function in the handler will format the text change to the specific format after user enter 10 nueric values.
ko.bindingHandlers.formatPhoneNumber = {
init: function (element, valueAccessor) {
$(element).on("keydown", function (event) {
if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
(event.keyCode == 65 && event.ctrlKey === true) ||
(event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) ||
(event.keyCode >= 35 && event.keyCode <= 39)) {
return;
}
else {
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
event.preventDefault();
}
}
});
},
update: function (element, valueAccessor) {
$(element).val(ko.unwrap(valueAccessor()));
formatPhone(element);
}
};
formatPhone = function (element) {
var phone= $(element).val().replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3");
$(element).val(phone);
}
it is very easy to use in the html page. here we will use textInput Binding from KnockoutJs framework to trigger the formatPhoneNumber update method immediately after the user key in 10 numbmers.
<input id="phone" class="form-control" type="text" placeholder="Home Phone" data-bind="textInput: homePhone, formatPhoneNumber:homePhone, validationElement:homePhone " maxlength="10" />
Thursday, August 17, 2017
How to solve KnockOut JS observable object not update with Canada Post autocomplete
when i integrate the Canada Post Autocomplete with an KnockOut JS web application, it looks very smooth, all the street related fields had been populated on autocomplete selection.
however, the observable object that binding to the control did not update automatically.
From Canada Post web site, I found this sample code for my own customization on auto populate event
I try use this in my javascript, but it never work out. actually we only need to setup the controller listen event.
var fields = [
{
element: customerType + "street-address", field: "Line1"
},
{
element: "street-address2", field: "Line2", mode: pca.fieldMode.POPULATE
},
{
element: "city", field: "City", mode: pca.fieldMode.POPULATE
},
{
element: "province", field: "ProvinceCode", mode: pca.fieldMode.POPULATE
},
{
element: "postalCode", field: "PostalCode"
},
{ element: "country", field: "CountryIso3", mode: pca.fieldMode.COUNTRY }
],
options = {
key: window.MyOwn.canadaPostKey
},
control = new pca.Address(fields, options);
control.listen('populate', function (address) {
customer.streetAddress(address.Line1);
customer.city(address.City);
customer.province(address.ProvinceCode);
customer.postalCode(address.PostalCode);
customer.country(address.CountryIso3);
});
however, the observable object that binding to the control did not update automatically.
From Canada Post web site, I found this sample code for my own customization on auto populate event
- <script type="text/javascript">
- addressComplete.listen('load', function(control) {
- control.listen("populate", function (address) {
- document.getElementById("line1").value = address.Line1;
- });
- });
- </script>
I try use this in my javascript, but it never work out. actually we only need to setup the controller listen event.
var fields = [
{
element: customerType + "street-address", field: "Line1"
},
{
element: "street-address2", field: "Line2", mode: pca.fieldMode.POPULATE
},
{
element: "city", field: "City", mode: pca.fieldMode.POPULATE
},
{
element: "province", field: "ProvinceCode", mode: pca.fieldMode.POPULATE
},
{
element: "postalCode", field: "PostalCode"
},
{ element: "country", field: "CountryIso3", mode: pca.fieldMode.COUNTRY }
],
options = {
key: window.MyOwn.canadaPostKey
},
control = new pca.Address(fields, options);
control.listen('populate', function (address) {
customer.streetAddress(address.Line1);
customer.city(address.City);
customer.province(address.ProvinceCode);
customer.postalCode(address.PostalCode);
customer.country(address.CountryIso3);
});
Subscribe to:
Posts (Atom)