The context is I have a radio button in my angular application that triggers a drop-down menu to appear. I'm attempting to attach an event listener that will fire off an AJAX request to a server and populate the drop-down list with the response. I'm using angular-bootstrap-select/bootstrap-select for the switch.
My initial approach was to simply add an ng-click directive to the div surrounding the button, which works, but the request is only sent if the user clicks on the white part of the button:
Image of button:
However the click doesn't register if the user clicks the grey part where it reads "All". I also tried wrapping the div in an anchor and attaching the ng-click to that but that did not work either.
I also tried to use the method in the documentation:
bootstrap-switch-event
My code:
$('input[id="mySwitch"]').on('switchChange.bootstrapSwitch', function(event, state) {
console.log('event triggered');
if ( !itemsCalled ) {
myService.items.get().$promise.then(function(response) {
$scope.itemList = response.items;
});
itemsCalled = true;
}
});
Template:
<input bs-switch id="mySwitch" ng-model="item" type="radio" switch-on-text="All" switch-off-text="Custom" switch-on-color="grey" switch-off-color="blue" switch-animate="true" switch-size="small" ng-value="'All'" ng-true-value="'All'" ng-false-value="'Custom'">
And a bunch of variations of this with no success. I'm pretty new to angular so I'm not sure if I'm going about this the wrong way or not.
If you want to make the Ajax call when the switch change from "Custom" to "All" :
function Controller($scope) {
$scope.$watch('item', function(newValue, oldValue){
if(newValue === "All") {
// Ajax call
alert("ajax");
}
})
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">
<input ng-model="item" type="radio" ng-value="'All'" ng-true-value="'All'" ng-false-value="'Custom'">
<button ng-click="item = 'Custom'">Reset</button>
</div>
Related
edited to add:
here is the only way I've managed to make it work at the moment - I took the ko implementation of the 'checked' binding and made a few small mods. Seems a bit heavyweight and prone to breaking when the framework gets updated but hey ho...
working code pen
I have a collection of radio buttons backed off with a knockout vm. If a user attempts to change the selection, I would like to first present them with a confirmation window (i.e. 'are you sure?').
I have managed to make this work, but I'm not happy with the solutions - one was too complex, the other showed two radio buttons selected when the confirmation window appeared.
I would like to intercept the click so that the confirmation shows before the selection changes in the UI (or the backing observable). I've tried to use the mouseup or mousedown event bindings but nothing I do prevents the selection occurring after choosing to cancel the change.
Is it possible to intercept the click and prevent the change propagating if required?
js:
var model = {
checkboxOptions : ["yes","no","maybe"],
selectedOption : ko.observable(),
showConfirm:function(data,ev){
if(!confirm("go ahead?")){
//doesn't work
ev.stopPropagation();
ev.preventDefault();
return false;
}
}
}
ko.applyBindings(model);
html:
<p>
<!-- ko foreach:checkboxOptions -->
<input type="radio" data-bind="event: {mouseup:$parent.showConfirm, click:null, mousedown:null}, value:$data,checked:$parent.selectedOption"/><span data-bind="text:$data"></span>
<!-- /ko -->
</p>
<p data-bind="text:selectedOption"></p>
codepen here
Since you want to change the way knockout checked binding works I would probably customise it with a bindingHandler, something like
<input type="radio" data-bind="radioWithConfirm: { selected: $parent.selectedOption }, value: $data"/>
ko.bindingHandlers.radioWithConfirm = {
init: function(element, valueAccessor) {
var options = valueAccessor();
$(element).on('click', function(event) {
if (!confirm('really?')) {
event.preventDefault();
return false;
} else {
options.selected(this.value);
return true;
}
});
}
}
CodePen here
I have page with around 20 to 30 controls based on the query string values. I need to change a button as disabled based on the value changes in the controls. For examble in the list of Check boxes if something is checked or unchecked, some texts added or removed etc... for all the controls.
The controls are textbox, option buttons, check boxes, select controls and list boxes.
I don't want to add static methods to all controls. I do have an idea of doing the late binding to all the controls and to attach events. And that events will disable the button whenever the event gets fired.
Is there any other way to do this functionality in a simple way(Like Keypress or using event property window object)?
As #ekhaled pointed out you can use the same handler to handle all the click and change events.
Here's a somewhat convoluted example:
<div id="container">
<input id="input1" type="text" value="" />
<select>
<option value="1">ABC</option>
<option value="2">EFG</option>
</select>
<input type="button" value="Submit" />
</div>
and the javascript for it:
$('#container').on("change click", ":input", function (event) {
if (event.target.nodeName == "SELECT") {
if ($(event.target).val() == "2") {
console.log("disable");
$(":button").prop("disabled", true);
} else {
$(":button").prop("disabled", false);
console.log("enable");
}
}
if (event.target.id == "input1" && $(event.target).val() == "") {
$(":button").prop("disabled", true);
}
});
See it working here.
However if you main concern is validation you should have a look at jquery validation
With jQuery validation you can set specific rules for each of the inputs that will make up the validation of the whole form. It is very customizable, you can change where and how the errors are displayed, when is the validation triggered, etc.
You can use event delegation and bind your event to the parent element, and then write all your logic inside that one event handler.
Can't really show you much, because you haven't included any examples or code. But something along the lines of:
$("body").on('change click', 'input, select', function(){
var _this = $(this);
if(_this.is('input[type=checkbox].className')){
//follow one logic
}
if(_this.is('input[type=radio].className')){
//follow another logic
}
//etc, etc
})
I want to disable my div with image and click event that event does not call. I try do it with KO:
<div title="Delete Series" class="deleteSeriesButton" data-bind="css: { disabled: true}" ></div>
but this does not work with div.
Can I do it without unbind click event?
If you are using KnockoutJS, then you have a view model.
And if you have a view model, you should be able to add an observable property that tells you whether the "delete series" button is enabled or disabled.
self.isDeleteEnabled = ko.computed(function() {
// your code that tells whether the button is enabled or not
});
And let's say you in your view model the click action, like this:
self.clickAction = function() {
// do what you want to do
}
Thne, you can make your "click" binding dependent on this observable, like this:
<div class="button" data-bind="click: isDeleteEnabled() ? clickAction : null">
If the isDeleteEnabled observable returns true, then the button is clickable, otherwise it's not.
I made a fiddle so you can see how it's done in a real example.
you can block the div using the jQuery blockUI plugin.
link to blockUI
I have a problem which I don't know is related to the meteor implementation of events or to Javascript events in general.
I have a textbox attached to a "change" event.
Next to it, I have a button attached to a "click" event.
When I do a change in the textbox and click the button, the click event does not fire (only the change event does). So I have to click the button two times for the click event to fire.
In Firefox, it works if I attach a mousedown event instead of the click event to the button. In Chrome it doesn't work either ways.
Minimal code reproducing the problem:
JAVASCRIPT: testevent.js
if (Meteor.isClient) {
Session.set("something", "something");
Template.hello.foo = function() {
return Session.get("foo");
};
Template.hello.something = function() {
return Session.get("something");
}
Template.hello.events({
'click .buttonid' : function () {
console.log("click !");
},
'change .textid' : function (e,t) {
console.log("change !");
var bar = e.target.value;
Session.set("foo",bar);
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
HTML: testevent.html
<head>
<title>testevent</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<input type="text" class="textid" value="{{foo}}"/>
<input type="button" class="buttonid" value="{{something}}" />
</template>
When I replace class with id the click event fire, but when I have multiple fields with the same id the events work only on one field.
The issue has to do with the hello.foo:
Template.hello.foo = function() {
return Session.get("foo");
};
and the fact that the value of foo is used to reactively populate the text input. If you remove the hello.foo function everything works as expected. When the user clicks the button, the change event fires which sets the "foo" session variable which in turn causes the template to re-render. I think the rendering process clears the remaining event queue, so the click handler never fires.
There are a couple of ways you can fix this. An easy (but crude) way is just to delay setting the session variable in the change event handler. For example:
Meteor.setTimeout(function(){Session.set("foo", bar);}, 100);
Obviously you would need to choose an appropriate delay and that may be browser/data dependent. Alternatively, you can just put the text input in its own template. For example:
<template name="hello">
{{> helloText}}
<input type="button" class="buttonid" value="{{something}}" />
</template>
<template name="helloText">
<input type="text" class="textid" value="{{foo}}"/>
</template>
After binding the events properly to this new template, you will find that helloText will be rendered separately from hello and thus your events will be preserved.
The client is making a request to the server.
I need to take part of that request, and make the form button work with Ajax.
This piece of code works perfectly for links:
var pagination_render = function() {
var pagination = $('.pagination a');
pagination.each(function() {
$(this).click(function(event) {
load_server(this.href, '.houseindex');
return false;
});
});
};
pagination_render();
I tried numerous things for making the Ajax button work, and this is one of the tries:
var contact_user = function () {
$('.expanded').find('#submit').each(function() {
$(this).unbind('click');
});
$('.expanded').each(function() {
$(this).find('#submit').click(function(event) {
form_submit($(this).parent(), '.contactuser .msg');
return false;
});
});
}
Whenever there is a successful Ajax call, it goes through all of the expanded items, and then binds a click event.
Now, sometimes this code works, and sometimes it doesn't.. When it doesn't work, it disables other events (toggle links) I have set up.
It seems as if I need to wait a few ms for it to load the component into the DOM.. Do I?
So I get that when you call contact_user you:
First unbind any previous binded click events from the submit button. I see one possible problem there and is that you are looking for an id of #submit. You should only have one id in a single page. Therefore you only need to use $('#submit').each(...) or if you have several submit buttons in the page either use a class if there are several submit buttons inside an .expanded item or just use $('.expanded :submit')
Adding a custom event when clicking the submit button. Same thing, you can simplify this by $('.expanded :submit') or if you truly only have one button with an id of submit (quite confusing). Go with $('#submit').
In conclusion:
var contact_user = function(){
$('.expanded :submit').unbind('click');
$('.expanded :submit').click(function(){
form_submit($(this).parent(), '.contactuser .msg');
return false;
});
};
the :submit selector will select all <input type="submit" />.