Html
<div class="col-xs-4">
<div class="form-group">
<label>
<input type="radio" name="r1"
data-bind="checked: EmployeeTypeChecked"
value="FT" class="minimal" />
Full Time Employee
</label>
<label>
<input type="radio" name="r1" value="DE"
data-bind="checked: EmployeeTypeChecked" class="minimal" />
Daily Wages
</label>
<label>
<input type="radio" name="r1" value="OD"
data-bind="checked: EmployeeTypeChecked" class="minimal" />
On demand
</label>
</div>
</div>
knockout code
window.employeeApp = {};
window.employeeApp.DataContext = {
createEmployee: function (data) {
return new employeeApp.DataContext.EmployeeModel(data);
},
EmployeeModel: function (data) {
data = data || {};
var self = this;
self.EmployeeTypeChecked = ko.observable(false),
self.toJs = function () {
return ko.toJS(self);
};
self.toJson = function () {
return ko.toJSON(self);
};
}
}
window.employeeApp.ViewModel = function () {
var selectedEmploeyee = ko.observable(),
init = function () {
selectedEmploeyee(employeeApp.DataContext.createEmployee());
};
return {
init: init,
selectedEmploeyee: selectedEmploeyee,
};
}();
ko.applyBindings(employeeApp.ViewModel, $('.page_script')[0]);
employeeApp.ViewModel.init();
If I remove iCheck plugin style it works; with iCheck plugin it doesn't work
correctly.
For example refer to this knockout link
you need to create a custom binding...in order to use the iCheck plugin.. with knockout..
ko.bindingHandlers.yourBindingName= {
init: function (element, valueAccessor) {
$(element).iCheck({
checkboxClass: 'icheckbox_minimal-grey',
increaseArea: '10%'
});
$(element).on('ifChanged', function () {
var observable = valueAccessor();
observable($(element)[0].checked);
});
},
update: function (element, valueAccessor) {
var value = ko.unwrap(valueAccessor());
if (value) {
$(element).iCheck('check');
} else {
$(element).iCheck('uncheck');
}
}
};
and you can use it like this..
<p>Send me spam: <input type="checkbox" data-bind="yourBindingName: wantsSpam" /></p>
instead of using the knockout "checked" binding
<p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam" /></p>
You need to bind event with your radio button like this
ko.bindingHandlers.RadioButton = {
init: function (element, valueAccessor) {
$(element).iCheck({
radioClass: 'Class Name'
});
$(element).on('ifChecked', function () {
var observable = valueAccessor();
observable.checked(true);
});
},
update: function (element, valueAccessor) {
var observable = valueAccessor();
}
};
Related
I have two checkboxes that I would like to implement following logic:
if both are OFF, that is allowed, if one checkbox is ON, if the other is to be ON (checked) then the first one must toggle to OFF and vice versa
How can I do this with html and ko.js?
This is the code that i got for toggling:
var viewmodel = function(){
var self = this;
self.checkA = ko.observable(true);
self.checkB = ko.pureComputed({
read: function(){
return !self.checkA()
},
write: function(value){
value? self.checkA(false) : self.checkA(true);
},
owner: self
});
};
ko.applyBindings(new viewmodel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
A
<input type="checkbox" data-bind="checked: checkA" />
B
<input type="checkbox" data-bind="checked: checkB" />
Since the value of B isn't merely a function of the value of A (both can be false) you'll have to have a second observable to store its state independently. Then for your logic I recommend using ko.subscribe instead of a computed function to react to the changes to either value.
var viewmodel = function() {
var self = this;
self.checkA = ko.observable(true);
self.checkB = ko.observable(false);
self.checkA.subscribe(function(value) {
if (value) self.checkB(false); //also clear B
});
self.checkB.subscribe(function(value) {
if (value) self.checkA(false); //also clear A
});
};
ko.applyBindings(new viewmodel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
A <input type="checkbox" data-bind="checked: checkA" />
B <input type="checkbox" data-bind="checked: checkB" />
I have the below model
var CountryScopeVM = function (data, root) {
CountryScopeVM.call(this, data);
var self = this;
this.isSelected = ko.observable();
this.centralImpLowHeadCount = ko.observable();
this.load(data);
}
};
this.countryScopes = ko.observableList(CountryScopeVM, data.countryScopes, this);
And I have the below code which gets called when a checkbox is selected. What I am trying to do here is have all the centralImpLowHeadCount inside the countryscope array get updated when the main checkbox is checked but it is not updating and I don't see the change in the UI.
selectAllLOWImplementation: function (data, event) {
var select = $(event.target).is(':checked');
ko.utils.arrayForEach(model.countryScopes() || [], function (countryScope) {
countryScope().centralImpLowHeadCount == select;
});
return true;
}
HTML
<input type="checkbox" data-bind="checked: hasSelectedLOWImplementation, click: selectAllLOWImplementation" />
<td><input type="checkbox" data-bind="checked: centralImpLowHeadCount, enable: isOn" /></td>
thank you for looking into this.
I have the following example built: http://jsfiddle.net/zm381qjx/5/
This is a menu list builder. When you add a menu, an edit form pops up. Using protectedObservable so that i can either commit or reset (as per code). One functionality, which i am having problems with, is there is radio button list (for TypeId), and depending on the value (10 = Url, 20 = Category, 30 = Page), you set the respective properties (10 = Url, 20 = CategoryId, 30 = PageId).
Flicking through the radio buttons, if Url is selected, another textbox should show (based on urlVisible) so user can enter the Url. I have added a span with text: TypeId.temp so i can see the temporary value. This is very irregular. Try to flick through several times.
Any help will be greatly appreciated.
My HTML
<a class="btn btn-primary" data-bind="click: addMenu">Add Menu</a>
<ul data-bind="foreach: Menus">
<li></li>
</ul>
<div class="panel panel-default" data-bind="slideIn: editMenuItem, with: editMenuItem">
<div class="panel-body">
<div class="form-group">
<label for="MenuName">Name: </label>
<input type="text" id="MenuName" data-bind="value: Name" class="form-control" />
</div>
<label class="radio-inline">
<input type="radio" name="MenuTypeId" value="10" data-bind="checked: TypeId" /> Url
</label>
<label class="radio-inline">
<input type="radio" name="MenuTypeId" value="20" data-bind="checked: TypeId" /> Category
</label>
<label class="radio-inline">
<input type="radio" name="MenuTypeId" value="30" data-bind="checked: TypeId" /> Page
</label>
<div class="form-group" data-bind="visible: urlVisible">
<label for="MenuUrl">Url: </label>
<input type="text" id="MenuUrl" data-bind="value: Url" class="form-control" />
</div>
<br />
<p>TypeId.temp = <span data-bind="text: TypeId.temp"></span></p>
<br /><br />
<input type="button" class="btn btn-success" value="Update" data-bind="click: commit" /> or
Cancel
</div>
</div>
My JS:
var vm = null;
//wrapper for an observable that protects value until committed
ko.protectedObservable = function (initialValue) {
//private variables
var _temp = ko.observable(initialValue);
var _actual = ko.observable(initialValue);
var result = ko.dependentObservable({
read: function () {
return _actual();
},
write: function (newValue) {
_temp(newValue);
}
});
//commit the temporary value to our observable, if it is different
result.commit = function () {
var temp = _temp();
if (temp !== _actual()) {
_actual(temp);
}
};
//notify subscribers to update their value with the original
result.reset = function () {
_actual.valueHasMutated();
_temp(_actual());
};
result.temp = _temp;
return result;
};
ko.bindingHandlers.slideIn = {
init: function (element) {
$(element).hide();
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (value) {
$(element).stop().hide().slideDown('fast');
} else {
$(element).stop().slideUp('fast');
}
}
};
var Menu = function (Id, Name, TypeId, CategoryId, PageId, Url) {
var self = this;
/* Core Properties */
self.Id = ko.observable(Id);
self.Name = ko.protectedObservable(Name);
self.TypeId = ko.protectedObservable(TypeId);
self.CategoryId = ko.protectedObservable(CategoryId);
self.PageId = ko.protectedObservable(PageId);
self.Url = ko.protectedObservable(Url);
/* Virtual Properties */
self.urlVisible = ko.computed(function () {
return self.TypeId.temp() == "10";
}, self);
/* Virtual Functions */
self.editMenu = function (data) {
if(vm.editMenuItem()) {
vm.editMenuItem(null);
}
vm.editMenuItem(data);
};
/* Core Functions */
self.commit = function () {
if (self.Name.temp() == '' || self.Name.temp() == null) {
alert('Please enter a name.'); return;
}
self.Name.commit();
self.TypeId.commit();
self.CategoryId.commit();
self.PageId.commit();
self.Url.commit();
vm.editMenuItem(null);
};
self.reset = function () {
self.Name.reset();
self.TypeId.reset();
self.CategoryId.reset();
self.PageId.reset();
self.Url.reset();
vm.editMenuItem(null);
};
};
var ViewModel = function() {
var self = this;
/* Core Properties */
self.Menus = ko.observableArray([]);
/* Virtual Properties */
self.editMenuItem = ko.observable(null);
self.addMenu = function(){
var menu = new Menu(0, "New Menu", "10", 0, 0, "");
self.Menus.push(menu);
self.editMenuItem(menu);
};
};
$(function () {
vm = new ViewModel();
ko.applyBindings(vm);
});
If you change your radio button binding to
<input type="radio" name="MenuTypeId" value="10" data-bind="checked: TypeId.temp" />
The temp id will be changed accordingly and radio button behaviour is consistent, but not with TypeId as value.
also the protectedObservable binding the radio button value is not playing nice
When you manually click the radio the TypeId value is never changed (as you are not committing the value) and I guess that as the radio button value never changes from 10 , it is not recognizing the subsequent manual clicks on Url radio button.
I updated the value using a button and it is changing accordingly; but then it will not move the value from that TypeId on subsequent radio button clicks
And the problem is still appearing for protectedObservable binding but not with a simple observable.
Code which explores this idea further: http://jsfiddle.net/zm381qjx/101/
I have the following HTML:
<select id="EmpName" data-bind="value: Employee.EmpName, event: { change: $root.updateEmployee }"></select>
<input disabled type="text" id="EmpNum" data-bind="value: Employee.EmpNum, valueUpdate: 'input'" />
<input disabled type="text" id="EmpClass" data-bind="value: Employee.EmpClass, valueUpdate: 'input'" />
<input disabled type="text" id="EmpDept" data-bind="value: Employee.EmpDept, valueUpdate: 'input' " />
<input disabled type="text" id="EmpStat" data-bind="value: Employee.EmpStat, valueUpdate: 'input'" />
And it's bound by the following ViewModel:
generalViewModel = function (thisData) {
var self = this;
this.Incident = ko.mapping.fromJS(thisData.Incident);
this.Employee = ko.mapping.fromJS(thisData.Employee);
this.updateEmployee = function () {
var employeeName = self.Employee.EmpName;
$.getJSON('/Incidents/GetEmployee', { EmployeeName: employeeName }, function (data, status, xhr) {
var newEmp = ko.mapping.fromJS(data);
self.Employee(newEmp);
});
}
this.refreshData = function (incID) {
GetIncidentGeneralInfo(incID, node);
}
this.savetoServer = function (incID, buttonID) {
var incident = ko.toJSON(self.Incident);
var employee = ko.toJSON(self.Employee);
$.post('/Incidents/SaveIncident', { IncidentID: incID, JSONIncident: incident, JSONEmployee: employee, button: buttonID }, function (data, status, xhr) {
self.refreshData(data);
});
}
}
ko.applyBindings(new generalViewModel(data), document.getElementById(node));
Everything is working quite nicely, with the exception of the updateEmployee function. The JSON is returning the new Employee information, but the textboxes aren't updating. I'm doing something silly incorrectly, and I can't quite figure out wat
Instead of
var newEmp = ko.mapping.fromJS(data);
self.Employee(newEmp);
You should do
ko.mapping.fromJS(data, self.Employee);
This will update all of the observable properties on self.Employee that were created by the first call to ko.mapping.fromJS.
I need to do following things: When user checks the checkbox, some function is called.
<input type="checkbox" data-bind="what to write here?" />
and in model:
var viewModel = {
this.someFunction = function() {
console.log("1");
}
};
I have not found anything about this is documentation here.
What you need is the click binding:
<input type="checkbox" data-bind="click: someFunction" />
And in your view model:
var ViewModel = function(data, event) {
this.someFunction = function() {
console.log(event.target.checked); // log out the current state
console.log("1");
return true; // to trigger the browser default behavior
}
};
Demo JSFiddle.
Or if you want to you use the checked binding you can subscribe on the change event of your property:
<input type="checkbox" data-bind="checked: isChecked" />
And in your viewmodel:
var ViewModel = function() {
this.isChecked = ko.observable();
this.isChecked.subscribe(function(newValue){
this.someFunction(newValue);
}, this);
this.someFunction = function(value) {
console.log(value); // log out the current state
console.log("1");
}
};
Demo JSFiddle.