I have a knockout view model that is set up as an observable as my main view model. In the child element, it seems that I can't set up data-bind="click: the same way that I can when I am in the parent element.
My html:
<button id="myButton" type="button" class="btn btn-lg btn-primary" data-bind="click: test">Click Me</button>
In my main view model:
self.childElement = ko.observable(new childElementVm());
and in childElementVm
var childElementVm= function () {
var test = function(){
alert('this is a test');
}
}
what do I need to do differently to use data-bind="click: test" here?
To note, my applyBindings is fine (other knockout observables are functioning correctly) and the button is contained inside of a <div data-bind="with: childElement"
EDIT: here is a fiddle
Your test function is scoped to the childElementVmonly. Change your implementation to this:
var childElementVm= function () {
this.test = function(){
alert('this is a test');
}
}
or this:
var childElementVm= function () {
var self = this;
self.test = function(){
alert('this is a test');
}
}
Here is a working example
Related
I'm totally new to angular and I try to use angular-bootstrap-datetimepicker in my project. My html code is:
<span class="input-group-btn" ng-class="{open: openedDP}">
<button type="button" class="btn btn-default btn-sm" ng-click="open()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
<ul class="dropdown-menu" role="menu">
<datetimepicker ng-model="abc"
on-set-time="close(new, old)">
</datetimepicker>
</ul>
</span>
<input id="abc" ng-model="abc" class="form-control" date-time-input="DD-MM-YYYY HH:mm:SS" />
I wanted to close a calendar when user clicks anywhere outside it. I almost copy-pasted the code from ui.bootstrap. Original one is inside directive and looks like this:
var documentClickBind = function(event) {
if (scope.isOpen && event.target !== element[0]) {
scope.$apply(function() {
scope.isOpen = false;
});
}
};
scope.$watch('isOpen', function(value) {
if (value) {
scope.$broadcast('datepicker.focus');
scope.position = appendToBody ? $position.offset(element) : $position.position(element);
scope.position.top = scope.position.top + element.prop('offsetHeight');
$document.bind('click', documentClickBind);
} else {
$document.unbind('click', documentClickBind);
}
});
My version (inside controller):
var documentClickBind = function (event) {
if ($scope.openedDP) {
$scope.$apply(function () {
$scope.openedDP = false;
});
}
};
$scope.$watch('openedDP', function (value) {
if (value) {
$timeout(function() {
$document.bind('click', documentClickBind);
}, 0, false);
} else {
$document.unbind('click', documentClickBind);
}
});
I removed "element" variable because I don't have it in my controller and it seems to work, but I don't know why. Maybe it works just by chance? Why clicking inside calendar is different than clicking anywhere else? In addition I'd like to avoid creating multiple functions like this when I have multiple datepickers on a page.
The behavior you want is built-in to the bootstrap dropdown, if you have bootstrap already in your project you might consider making use of its dropdown.
If not, you could create a custom directive on the page that broadcasts a 'page-clicked' event when the user clicks on another part of the page, then each controller can listen for that event on their scope and react accordingly.
Hi I am trying to get selected value of dropdown in Knockout js so that I can hide/ show other elements based on selection. Below is what I have tried.
What is happening that I am able to get right value on button click but not on dropdown selection change.
Below is my code. The button gives right value, but dropdown selection change event gives previous value & not the selected one.
JS
function ViewModel() {
var self = this;
self.optionValues= ko.observableArray(["Test1", "Test2", "Test3"]);
self.selectedValue = ko.observable();
self.save = function() {
alert(self.selectedValue());
}
}
ko.applyBindings(new ViewModel());
HTML
<select data-bind="event:{ change: save},options: optionValues, value: selectedValue"></select>
<button data-bind="click: save">Save</button>
Instead of the change event binding binding, you should subscribe directly on your selectedValue observable, and call your logic from there:
function ViewModel() {
var self = this;
self.optionValues = ko.observableArray(["Test1", "Test2", "Test3"]);
self.selectedValue = ko.observable();
self.selectedValue.subscribe(function(newValue) {
self.save();
});
self.save = function() {
alert(self.selectedValue());
}
}
ko.applyBindings(new ViewModel());
Html:
<select data-bind="options: optionValues, value: selectedValue"></select>
<button data-bind="click: save">Save</button>
Demo JSFiddle.
I have a knockout app and within it I have a function which shows/hides elements on the page depending on the selected option. The button that has been selected to activate a particular toggle will have an 'active' class so that it 'stands out' from the others and is clearly visible that that's the selected option. My problem is that I've created a knockout function to toggle the active class but it's triggering the active state on all of the buttons rather than the selected button and I'm not sure why?
var viewModel = function(){
var self = this;
self.isActive = ko.observable(false);
self.toggleActive = function(data, event){
self.isActive(!self.isActive()); //toggle the isActive value between true/false
}
}
<button data-bind="click: toggleActive, css : {'activeStyle' : isActive}">Toggle Active</button>
<button data-bind="click: toggleActive, css : {'activeStyle' : isActive}">Toggle Active</button>
<button data-bind="click: toggleActive, css : {'activeStyle' : isActive}">Toggle Active</button>
Fiddle: http://jsfiddle.net/amMup/5/
You only have one viewmodel for all three buttons. That means you only have a single "isActive" flag that all buttons are bound to.
Instead, use an array of items and a foreach loop to render each one. Here's a tweaked version of your view model:
var viewModel = function(){
var self = this;
self.items = [
{ isActive: ko.observable(false) },
{ isActive: ko.observable(false) },
{ isActive: ko.observable(false) }
];
self.toggleActive = function(data, event){
data.isActive(!data.isActive());//toggle the isActive value between true/false
}
}
var myModel = new viewModel();
ko.applyBindings(myModel);
And the HTML is simplified:
<div data-bind="foreach: items">
<button data-bind="click: $parent.toggleActive, css : {'activeStyle' : isActive}">Toggle Active</button>
</div>
Note the use of $parent to access the parent's binding context. When you're inside a foreach loop, the binding context is the individual item pulled from the foreach loop. By accessing $parent you "reach up" to the object that contains the items property -- which, in your case, is the viewmodel where the toggleActive exists.
Here's an updated fiddle: http://jsfiddle.net/psteele/amMup/6/
This is because you have them all bound to the same observable.
http://jsfiddle.net/Kohan/fdzqJ/
Js
var viewModel = function(){
var self = this;
self.isActive1 = ko.observable(false);
self.isActive2 = ko.observable(false);
self.isActive3 = ko.observable(false);
self.toggleActive = function(data){
data(!data());
}
}
var myModel = new viewModel();
ko.applyBindings(myModel);
HTML
<button data-bind="click: function(){toggleActive(isActive1)}, css : {'activeStyle' : isActive1}">Toggle Active</button>
<button data-bind="click: function(){toggleActive(isActive2)}, css : {'activeStyle' : isActive2}">Toggle Active</button>
<button data-bind="click: function(){toggleActive(isActive3)}, css : {'activeStyle' : isActive3}">Toggle Active</button>
Another way:
<button data-bind="click: function(){setActive('1')}, css: buttonActive() == '1' ? 'active' : '' ">Toggle Active</button>
var viewModel = function(){
var self = this;
self.buttonActive = ko.observable(false);
self.buttonActive = function(index){
self.buttonActive(index);
}
}
var myModel = new viewModel();
ko.applyBindings(myModel);
Given the following code:
<body data-bind="with: localization">
<button id="btnLogin">Login</button>
</body>
And the following javascript
$(function () {
$('#btnLogin').click(function () {
console.log('Clicked');
});
ko.applyBindings(MainView);
});
My console is empty if i click on the button
If I change the markup to this:
<body data-bind="">
<button id="btnLogin">Login</button>
</body>
I get "clicked" in my console when testing.
How can I get my events to work properly?
Here's an alternate way to approach your problem, using Knockout to handle clicks:
<body data-bind="with: localization, click: activate">
<button id="btnLogin">Login</button>
</body>
And define the activate function on your ViewModel:
var Vm = function() {
this.activate = function() {
console.log('view model activated, possibly through click');
};
}
This allows you to re-use the activate logic elsewhere.
I've got a very simple View Model:
var ViewModel = function() {
this.showRow = ko.observable(false);
this.toggleVisibility = function() {
if(this.showRow == true){
this.showRow = false;
}
else{
this.showRow = true;
}
alert('showRow is now '+this.showRow); //only here for testing
};
};
with equally simple markup:
Toggle
<br />
<table>
<tr data-bind="visible: showRow">Some Text</tr>
</table>
My problem is, that when the link is clicked, the alert box shows (displaying the correct value - true/false)
However, the visible binding on the tr element doesn't seem to work - either initially (the row should be invisible on load) nor when the value of showRow toggles.
jsFiddle of above- http://jsfiddle.net/alexjamesbrown/FgVxY/3/
You need to modify your html as follows:
<table>
<tr data-bind="visible: showRow"><td>Some Text</td></tr>
</table>
And JavaScript as follows:
var ViewModel = function() {
var self = this;
self.showRow = ko.observable(false);
self.toggleVisibility = function() {
self.showRow(!self.showRow());
alert('showRow is now ' + self.showRow());
};
};
ko.applyBindings(new ViewModel());
Syntax to set the value to observable property is: self.showRow(value);
If need to have tags inside of tags.
I've also modified your fiddle to simplify the javascript and follow newer code practices with regard to "this". See http://jsfiddle.net/FgVxY/4/