I am using Select2 as multiselect on an input field. I am trying to find out which choice is being clicked, but if I look at the event thrown when clicking a choice ("choice-selected") all I can find is event.target.value which is the data array with all selected options (choices). Basically I want to access the clicked value so I can let the user edit a custom attribute in that specific choice. How could I go about doing that?
JSFiddle of the problem: http://jsfiddle.net/JtTTF/
$(test).bind("choice-selected", function(e) {
alert(e.target.value);
// this is where i would like to access the clicked choice id so i can edit the custom data attribute "reason"
});
I ran into this as well. After examining the select2.js source code, I found that the choice-selected event passes a second parameter: the dom element you clicked.
This dom element contains a data object with key "select2-data".
Your code might look something like this:
$(test).on("choice-selected", function(e, choice) {
var data = $(choice).data('select2-data');
alert(data.reason ? 'Reason: ' + data.reason : 'No Reason');
});
I've updated your jsfiddle accordingly.
Try
var selected = {};
$(test).change(function () {
var selections = $(this).select2('data');
$.each(selections, function (idx, obj) {
if (!selected[obj.id]) {
selected[obj.id] = obj;
$('#selectedText').text(JSON.stringify(obj));
return false;
}
})
});
Demo: Fiddle
Note: Haven't seen whether there is inbuilt support to do this, but a custom implementation
Related
I want to perform operation after successfully loaded the partial page using $http service in angular.
The operation is to check the checkbox based on the scope value.
Please anyone help me.
Source Code here:
This is actual code.
$http({
url : './resources/staticPages/custom-object-filter.html',
method : "GET"
}).success(function(data, status) {
$scope.data = data;
jQuery("objectViewPartial").html($compile($scope.data)($scope));
//console.log($scope.selected);
if(angular.equals($scope.selected, "ShowActivatedObjects")) {
$("#ShowActivatedObjects").attr('checked','true');
} else {
$("#ShowActivatedObjects").attr('checked','false');
}
}).error(function(data, status) {
console.log("some error occured partial page");
});
After getting success the below code is not working.
if(angular.equals($scope.selected, "ShowActivatedObjects")) {
$("#ShowActivatedObjects").attr('checked','true');
} else {
$("#ShowActivatedObjects").attr('checked','false');
}
I placed this code inside of success function.
Please advice where i need to place this code.
A short Angularjs excursus:
In general you should minimize the use of jQuery within angularjs as far as you can, because both concepts are working against each other.
Angularjs is based on bindings between scope variables and the template expressions. So for a check box you can easy handle it without jQuery as follows:
A good explanation you can find here:
https://stackoverflow.com/a/14520103/4852206
What you are seeing here is, that you i.ex. can bind the checkbox inputs to an array. If you are changing the array content, the checkboxes are listening and do change there state (checked or unchecked) just on the fly without the need of checking if it is active and without the Jquery dom manipulation needs.
I wrote the above excursus, because you will run into huge unstructured and unreadable code if you will use your way as best practice. Also I am afraid, that you are using your code within your controller function. In Angularjs the controller is NOT for dom manipulation, you should only use it for setting / changing the scope variables or just a minimal business logic (in general avoid it here!) Business logic should go into services and dom manipulation should go into directive's.
Your question:
Please provide more information for your problem / logic. Please provide sample checkboxes, and sample information that you pull from the server via $http
Please provide also what you want to achieve exactly. Then we can help you with a clear answer.
Sorry I know this is no answer, but I cannot add comments actually cause I am quite new here.
EDIT
Ok thanks to your comment to #Likeee I think I got you. You have a set of checkboxes on your page. On page load you want to check which checkbox needs to be active. The logic which checkbox is active on pageload comes from the server side, is that correct? If yes I would handle it as follows with angular structure (I created a fiddle for a better understanding: https://jsfiddle.net/pfk9u3h0/4/)
First you need your HTML:
<body ng-app="myApp" ng-controller="AppController">
<label ng-repeat="filter in productFilter">
<!--
simply checking if the array contains the entry. if not, it is not selected. On a click event, the selected item is added to the array.
-->
<input
type="checkbox"
value="{{filter}}"
ng-checked="selection.indexOf(filter) > -1"
ng-click="toggleSelection(filter)"/> {{filter}}
</label>
"selection Array within SelectionService": <br />{{selection}} <br /><br />
as you see, the array is also updating when you check or uncheck a box
</body>
This HTML snipped does several things:
First it declares which controller (here "AppController" to use.
Second it creates a label with a checkbox inside. The label has the Angularjs directive ngRepeat and causes to show as much checkboxes as the array "productFilter" within AppController contains.
The Javascript contains a controller which is talking to your HTML and to a service. The service is also declared below.
Controller:
app.controller("AppController", function( $scope, SelectionService ) {
// available filter checkboxes
$scope.productFilter = ['Red pants', 'Green Pants', 'Yellow pants', 'Blue pants'];
// selected filter
// normally you just would have this: $scope.selection = ['Red pants', 'Blue pants'];
// But now you want to pull the selection elsewhere:
// The selection should go in a service, because it can happen, that other pageviews of your page shall
// change the values or even get the selection as well.
$scope.selection = SelectionService.selection; // Bind the selection to the service
// With the proper binding, you can change the selection within other modules / pages etc. and this
// checkbox fields will update based on the service data!
//I just initialize the service selection array, butbut you really want to pull it from server like this:
// SelectionService.loadSelection()
// .then(function(data) {
// if you like, yo can do sth. with this promise callback
// });
// Change selection for the clicked input field
$scope.toggleSelection = function toggleSelection(filter) {
var idx = $scope.selection.indexOf(filter);
// is currently selected
if (idx > -1) {
SelectionService.removeSelection(idx);
}
// is newly selected
else {
SelectionService.addSelection(filter);
}
};
});
With $scope.productFilter = ['Red pants', 'Green Pants', 'Yellow pants', 'Blue pants']; we declare an array over which we iterate within our HTML. This contains all checkboxes with names.
Now we need an array with all selected checkboxes. This is saved in $scope.selection and is bound to the service which i show at the end:
$scope.selection = SelectionService.selection;
The rest within the controller is just to set the new values, if you uncheck or check a checkbox
The Service:
app.service("SelectionService", function ($http, $q) {
var obj = {
selection : ['Red pants', 'Blue pants'],
loadSelection : function(){
var that = this;
var deferred = $q.defer();
var config = {
responseType : "json",
cache: true
}
$http.get("/getSelectionFromServer", null, config)
.success(function(response){
if(response) {
// IMPORTANT: Use a deep copy, otherwise you will loose the binding
angular.copy(response,that.selection);
}
deferred.resolve(response);
})
.error(function(){
deferred.reject();
});
return deferred.promise;
},
addSelection : function (filter) {
this.selection.push(filter)
},
removeSelection : function (index) {
this.selection.splice(index, 1);
};
return obj;
});
The Service is doing 4 things: It holds and initilizes (if you like) an array "selection". And it offers a method to load new data from server and save it to the array. Here it is important that you use the copy method, otherwise you will loose any binding. And it offers methods to set and remove selections.
in my example i dont use the load method, because I do not have any serverside scripts here...I just take the initialization values. But you should use my load method.
Hi your comparison is probably bad.
if(angular.equals($scope.selected, "ShowActivatedObjects")) {
I don't know what value is in $scope.selected, but i think this value is a checkbox state which is boolean type. So you are comparing boolean with string.
Check out https://docs.angularjs.org/api/ng/function/angular.equals
Finally i achieved my requirement:
// $scope.getCustomObjectsBasedOnObjectTypeSelection = getCustomObjectsBasedOnObjectTypeSelection;
$scope.selected = ['Show All'];
var IsActive = "";
$scope.objectSelection = function objectSelection(objectType) {
var idx = $scope.selected.indexOf(objectType);
// is currently selected
if (idx > -1) {
$scope.selected.splice(idx, 1);
}
// is newly selected
else {
$scope.selected.push(objectType);
}
};
I would like to know how to access jsTree node attributes after the node's checkbox was clicked.
I use $("#jstree").bind('check_node.jstree', function(e, data) { to trigger my code after the checkbox was clicked.
Now I want to access node's attributes. But I don't know how to use data object so I can get the attributes. So let's say in my jsfiddle I want to display the value of the attribute along with the text "clicked and checked"
Could you please explain how & why? I am lost how to reference jsTree/jQuery objects.
jsfiddle working sample
==== Update
In jsTree data definition node attributes could be defined. I want to programatically check the attributes and then fire different code base on the attributes. In my case "log" attribute.
data = [
{
"data": "Basics",
"attr":{"log":"shared"},
},
{
"data": "All",
"attr":{"log":"bdrs"},
}
]
you could just do:
$("#jstree").bind('check_node.jstree', function(e, data) {
$("#list").append('<BR>clicked and ' + node_is_check(data));
var node = data.rslt.obj;
console.log( node.attr("log") ); //shows bdrs when All is checked
});
Updated fiddle: jsFiddle Demo
Did you mean something like this
Using jquery I've added a change handler to a form.
This works when any input is changed BUT only if the user manually changes an input and not when some other code changes the input.
Is there any way to detect if a form has changed even if its inputs are changed by code?
Yes, there seems to be some confusion over this. In an ideal world you would expect the onchange event to happen whenever the inputs change but thats not what happens. I'm sure for good reasons to - maybe not.
One way I've overcome this obstacle is to capture the form state into a variable just after displaying it and then just before submitting it to check if the state has changed and to act accordingly.
An easy state to store is what the serialize function returns. An easy place to store the state is using the data functionality. Both serialize and data are available with jquery.
Of course you can use other different forms of state (some form of hash) or storage for this state (standard global variable for example).
Here is some prototype code:
If your form id is 'xform' then you can call the following code when the form has displayed:
$('#xform').data('serialize',$('#xform').serialize());
And then, when you need to check, for example just before a button submit you can use:
if($('#xform').serialize()!=$('#xform').data('serialize')){
// Form has changed!!!
}
You could wrap all this up into a copy & paste javascript snippet that will give you a formHasChanged() function to call wherever you need it (NOT TESTED):
$(function() {
$('#xform').data('serialize',$('#xform').serialize());
});
function formHasChanged(){
if($('#xform').serialize()!=$('#xform').data('serialize')){
return(true);
}
return(false);
}
But I'll stop here otherwise I'll create yet another jquery plugin.
Serializing the form is certainly an option, but it will not work if:
you want to know which fields have changed
it only needs to check a subset of the fields
dynamically adding or removing fields.
Fortunately, every form element has a default value associated with its object:
input, textarea : defaultValue
checkbox, radio : defaultChecked
select: defaultSelected
for ex: to ckeck if input or textarea has changed:
var changed = false;
$(":text,textarea").each(function(){
changed = this.value != this.defaultValue;
return !changed; // return if at least one control has changed value
});
This is easily achieved in JavaScript without jQuery. initChangeDetection() can be called multiple times:
function initChangeDetection(form) {
Array.from(form).forEach(el => el.dataset.origValue = el.value);
}
function formHasChanges(form) {
return Array.from(form).some(el => 'origValue' in el.dataset && el.dataset.origValue !== el.value);
}
Test on JS Bin
For older browsers that don't support newer arrow/array functions:
function initChangeDetection(form) {
for (var i=0; i<form.length; i++) {
var el = form[i];
el.dataset.origValue = el.value;
}
}
function formHasChanges(form) {
for (var i=0; i<form.length; i++) {
var el = form[i];
if ('origValue' in el.dataset && el.dataset.origValue !== el.value) {
return true;
}
}
return false;
}
Not in a regular way.
You can change with input and then trigger the change event.
$('#inputId').val('foo').trigger('change');
or with this:
$('#inputId').val('foo').change();
Here is what i did (i found my solution using zaf's answer)
$("form").change(function() {
$(this).data("changed","true");
});
$("input[type='submit']").click(function() {
if($("form").data("changed") == "true") {
var discard = confirm("Some unsaved changes. Discard them ?");
if(!discard) return false;
}
});
Try onchange attribute
According to W3c it should trigger anytime the content of an element, the selection, or the checked state have changed.
I'm trying to add categories to a drop down list using jQuery Ajax. When an option is selected I would like to load the subcategories.
The problem that I'm facing is that the addition of options to the drop down list by the Ajax function seems to trigger the change event as well. How can I avoid this or rewrite my code better in order to avoid this behavior?
Here's my code:
categoryHelper.loadLevel1 = function () {
// The control that needs to be filled with categories
var $control = $("#select1");
// This function runs $.getJSON() and fills the drop down list
// with option elements
fillDropDown(url, null, $control);
// When I select a value I want to run the function loadLevel2 which
// takes the currently selected value from level 1 as parameter
$control.change(categoryHelper.loadLevel2($control.val()));
};
Code for the fillDropDown:
function fillDropDown(url, parameters, dropdown) {
/// all data has been loaded</param>
$.getJSON(url, parameters, function (data) {
$(dropdown).empty();
$(dropdown).append(createOption("", ""));
$(data).each(function () {
$(dropdown).append(createOption(this.value, this.text));
});
});
}
All help is appreciated!
This line:
$control.change(categoryHelper.loadLevel2($control.val()));
will pass the result of calling categoryHelper.loadLevel2($control.val()) to .change(); if that isn't a function, then you're not going to be adding an event handler to the element but instead triggering any event handlers that are already bound. Change it to:
$control.change(function() {categoryHelper.loadLevel2($control.val())});
so that you're actually passing a function to .change(), and it should work.
function jsarea3() { document.getElementById("Txtarea3").title = document.getElementById("Txtarea3").value; }
function jsarea4() { document.getElementById("Txtarea4").title = document.getElementById("Txtarea4").value; }
function jsarea5() { document.getElementById("Txtarea5").title = document.getElementById("Txtarea5").value; }
The code above is to show data in a textbox area on mouse hover.
as you can see the code that run is same for all the 3 function the difference is only the ID
How can I pass ID dynamically
Like I can use the inner code as function as well for all the 3 and how to use it
and what about code like this the code given below
$('#button1').focus(function () {
$('#button1', window.parent.document).css("background-color", "#fcc63b");
}
});
if you are using jquery you can select your textareas like this
$("textarea").focus(function(){
this.title = $(this).val();
});
you can specify the selector to be more specific to the items that you want to manipulate
the function will be running when your textarea gain focus
take a look at jquery it's simplify your code
Since you use the same elements title and value you can store a reference instead of searching for it twice..
function jsarea(anId) {
var elem = document.getElementById(anId);
elem.title = elem.value;
}
and you can call it with jsarea('Txtarea3');
For the second code, it is jQuery code and it seems to change the background color of a button with the same id as the one that gets the focus in the parent window (when you use iframes)
You can use a single function which takes a parameter representing the id of the the element you wish to reference:
function jsarea(elementId) {
document.getElementById(elementId).title = document.getElementById(elementId).value;
}
You can call this like jsarea("Txtarea3"); if you want to affect the element with id "Txtarea3".
Use a parameter.
In addition, you should take a look at jQuery - it can really simplify DOM-manipulating code.
function jsarea(number) { document.getElementById("Txtarea" + number).title = document.getElementById("Txtarea" + number).value; }