Cant add a Jquery plugin inside a loop - javascript

Hi I have a JQuery plugin that takes an array of Orders and creates rows for each Order in the array. No issues here. However if one of these Orders meets a condition it should add a textbox in one of the TD cells. When I debug I can see it adding the textBox but when the next row is created which requires a textBox the previous textbox gets removed. i have this inside a close so not sure what to do. So the result is I only get textboxes in the last row.
If I add the textBox as html it works fine but I want it as a plugin as I need to bind several events KeyUp/Down MouseWheel, Click. etc
The textbox plugin control (gep_inputcontrol) just creates the html and binds events, nothing fancy.
Any help appreciated.
var _table = $('#orderTable', this);
for (var i = 0; i < params.orders.length; i++) {
var row = createRow(params.orders[i]);
_table.append(row);
}
function createRow(order){
var unmatchedStake = (order.requestedStake - order.matchedStake);
var partMatched = (unmatchedStake > 0);
var tr = $(String.format('<tr id="order_{0}" class="{1}"/>' ,order.orderId, ((i % 2) == 0) ? 'gep-altrow' : 'gep-row'));
tr.append(String.format('<td class="gep-icon gep-status">{0}</td>', order.orderStatusId));
tr.append(String.format('<td class="gep-selectionname">{0} {1} {2}</td>', GBEUtils.getEventName(order.eventClassifierFullName()), gep._settings.resources.general.polarity[order.polarityId], order.selectionName()));
tr.append(String.format('<td class="gep-odds betSlipRowPrice">{0}</td>', order.averageMatchedPrice));
tr.append(String.format('<td class="gep-unmatched betSlipRowStake">{0}</td>', com.base.formatDecimal(order.requestedStake - order.matchedStake,2)));
tr.append(String.format('<td class="gep-matched">{0}</td>', com.base.formatDecimal(order.matchedStake,2)));
tr.append(String.format('<td class="gep-action"><span class="gep-icon"/></td>', order.orderStatusId));
//var tablerow = $(String.format('#order_{0}',order.orderId), _table);
//(function (_table, tr, i, unmatchedStake, tablerow) {
if(unmatchedStake > 0)//part matched
{
$('.gep-unmatched', tr).gep_inputcontrol({
type:'STAKE',
ccSymbol:clientObject.state.ccSymbol,
value: unmatchedStake,
decimalValue:unmatchedStake,
onMouseWheeled: function(e, ev){
gep.inputControlWheeled(e, ev);
gep.calculateRowProfit(e, false);
return false;
},
onArrowClicked: function(e){
gep.onArrowClick(e);
return false;
}
});
//$('.gep-unmatched', tr).html($('.gep-unmatched', tr).html());
$('.gep-odds', tr).gep_inputcontrol({
type:'PRICE',
value:order.requestedPrice,
decimalValue:order.requestedPrice,
onMouseWheeled: function(e, ev){
gep.inputControlWheeled(e, ev);
gep.calculateRowProfit(e, false);
return false;
},
onArrowClicked: function(e){
gep.onArrowClick(e);
return false;
}
});
$('.gep-action .gep-icon', tr).addClass("gep-icon-delete");
$('.gep-icon-delete', tr).bind("click", function(){
alert("delete");
toggleCurrentBetSlipBet(this);
return false;
});
}
// })(_table, tr, i, unmatchedStake, tablerow);
return tr;
}
The textbox plugin creates a table with input box and two anchor tags.
/********************
GEP.gep_inputcontrol // stake input, price input box
********************/
(function ($) {
var _templatePrice = $('<table class="gep-inputcontrol" cellpadding="0" cellspacing="0"><tr><td rowspan="2"><input type="text" size="5" class="gep-inputcontrol-price" /></td><td><a tabindex="-1" href="javascript:void(0);" class="gep-inputup"></a></td></tr><tr><td> <a tabindex="-1" href="javascript:void(0);" class="gep-inputdown"></a> </td></tr></table>');
var _templateStake = $('<table class="gep-inputcontrol" cellpadding="0" cellspacing="0"><tr><td rowspan="2"><span class="gep-ccsymbol" /> <input type="text" size="5" class="gep-inputcontrol-stake" /> </td> <td> <a tabindex="-1" href="javascript:void(0);" class="gep-inputup"></a></td></tr><tr><td> <a tabindex="-1" href="javascript:void(0);" class="gep-inputdown"></a> </td></tr> </table>');
var _template;
var _settings = null;
var _instance;
var methods = {
init: function (options) {
_settings = options;
//options.type = 'STAKE'or 'PRICE'
_template = (options.type == 'STAKE')? _templateStake: _templatePrice;
$('.gep-ccsymbol',_template).html(options.ccSymbol);
this.html(_template);
$('input', this).attr('value', options.value);
$('input', this).attr('initialvalue', options.decimalValue);
$('input', this).attr('decimalValue', options.decimalValue);
$('input', this).bind("mousewheel", function (ev) {
_settings.onMouseWheeled.call(null, this, ev.originalEvent);
});
$('.gep-inputup', this).bind("click", function (e) {
_settings.onArrowClicked.call(null, this);
});
$('.gep-inputdown', this).bind("click", function (e) {
_settings.onArrowClicked.call(null, this);
});
_instance = this;
return this;
},
show: function (params) {
alert("show" + params);
},
hide: function () {
// GOOD
},
update: function (content) {
// !!!
}
};
$.fn.gep_inputcontrol = function (method) {
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.gep_inputcontrol');
}
};
})(jQuery);
To elaborate a bit more, I did some small unit tests
This works..
$('.gep-odds', clientObject.liveBetsPane).gep_inputcontrol({
type: 'PRICE',
value: 5,
decimalValue: 5,
onMouseWheeled: function (e, ev) {
gep.inputControlWheeled(e, ev);
gep.calculateRowProfit(e, false);
return false;
},
onArrowClicked: function (e) {
gep.onArrowClick(e);
return false;
}
});
This does NOT work...(Only puts TEXT box in last row) But I need to do it this way as I need values of each row.
$('.gep-odds', clientObject.liveBetsPane).each(function () {
$(this).gep_inputcontrol({
type: 'PRICE',
value: 5,
decimalValue: 5,
onMouseWheeled: function (e, ev) {
gep.inputControlWheeled(e, ev);
gep.calculateRowProfit(e, false);
return false;
},
onArrowClicked: function (e) {
gep.onArrowClick(e);
return false;
}
});
});

I removed dollar from the template and it worked fine.
var _templatePrice = $('<table cla...
is now
var _templatePrice = '<table cla...
Although it sets the html for the last row it was moving for the other rows.
Thanks to me.... :)

Related

How to change the text with JS

I am trying to modify this code, so after I create the column, and let's say I want to change the title of it, so I have the edit button, once I click that one, I want to be able to type and change the title of the column.
For the whole code click here.
function Column(name) {
if (name.length > 0) {
var self = this; // useful for nested functions
this.id = randomString();
this.name = name;
this.$element = createColumn();
function createColumn() {
var $column = $("<div>").addClass("column");
var $columnTitle = $("<h3>")
.addClass("column-title")
.text(self.name);
var $columnTitleEdit = $("<button>")
.addClass("btn-edit")
.text("Edit");
var $columnCardList = $("<ul>").addClass("column-card-list");
var $columnDelete = $("<button>")
.addClass("btn-delete")
.text("x");
var $columnAddCard = $("<button>")
.addClass("add-card")
.text("Add a card");
$columnDelete.click(function() {
self.removeColumn();
});
$columnAddCard.click(function(event) {
self.addCard(new Card(prompt("Enter the name of the card")));
});
$columnTitleEdit.click(function(event) { //How to edit this code here so i can rename the title of the Column?
self.editTitle();
});
$column
.append($columnTitle)
.append($columnDelete)
.append($columnAddCard)
.append($columnCardList)
.append($columnTitleEdit);
return $column;
}
} else if (name.length == 0) {
alert("please type something");
$(".create-column").click();
} else {
return;
}
}
Column.prototype = {
addCard: function(card) {
this.$element.children("ul").append(card.$element);
},
removeColumn: function() {
this.$element.remove();
},
editTitle: function() {
if (this.$element == "true") {
this.$element.contentEditable = "false"; //How to edit this code here so i can rename the title of the Column?
} else {
this.$element == "true";
}
}
};
All you have to do is to add an event listener to the edit button. The handler should either replace the title with a textarea, or add the contenteditable attribute to the title element. Here's an example:
// ...
var $columnTitleEdit = $("<button>")
.addClass("btn-edit")
.text("Edit")
.on("click", function(){ //The event listener
if ($(this).hasClass("btn-save")){ //If we're currently editing the title
$columnTitle.attr("contenteditable", false);
$(this).text("Edit").removeClass("btn-save");
} else { //If we're not editing the title
$columnTitle.attr("contenteditable", true).focus();
$(this).text("Save").addClass("btn-save");
}
});

How to properly add multiple elements event in jQuery custom plugin

I am trying to write my first jquery plugin and I'm having some difficulties trying to implement functions, events and triggers.
Here is the scenario in which I'm working.
I've multiple input box with same class eg. "numberTextBox"
Apply plugin directly to these classes eg. "$(".numberTextBox").inputNumericTextBox();".
I can also give settings in it.
Now plugin should allow only numeric value based on setting either given on default.
what I had in my mind is to properly convert and verify any given value. I want to use both onkeypress and onblur event. For that I wrote simple JavaScript program see here http://jsfiddle.net/wHgH5/29/.
I wanted to create jquery plugin so I can use in future easily with more friendly code.
On "return this each function" you can see I wrote keypress and blur function for that specific reason.
Problems which I am facing:
Firstly the blur event is not working so I can't trigger beforeBlurAction, afterBlurAction, onComplete functions and not to mention all the functionality in triggerBlurAction will not work.
Secondly even on keypress event it's assuming all "numberTextBox" input elements are same and doesn't apply separately. To understand it run the code snippet there are two input box with same classes, now type/press from keyboard "2.1.1" it will only allow "2.1" in that input box but on the second one it won't allow decimal. but if you empty first input box and it will allow writing single decimal on the second input box. I want to do it separately.
Check here https://jsfiddle.net/mzhe2rde/
//JQuery Custom Plugin inputNumericTextBox
(function($) {
jQuery.fn.inputNumericTextBox = function(options) {
var defaults = {
negativeAllow: true,
decimalAllow: true,
decimalError: false,
negativeSignError: false,
beforeKeypressAction: function() {},
afterKeypressAction: function() {},
beforeBlurAction: function() {},
afterBlurAction: function() {},
onError: function() {},
onComplete: function() {},
};
var settings = $.extend({}, defaults, options);
return this.each(function(i, element) {
$(document).on('keypress', element, function(e) {
triggerKeypressAction(e, element)
});
$(document).on('blur', element, function(e) {
alert(); //for testing but it's now working
triggerBlurAction(e, element)
});
});
function triggerKeypressAction(evt, element) {
settings.beforeKeypressAction.call(element, settings);
var regex;
var theEvent = evt || window.event;
var key = String.fromCharCode(theEvent.keyCode || theEvent.which);
if (/\./.test(key) && /\./.test($(element).val())) {
theEvent.returnValue = false;
if (theEvent.preventDefault) {
theEvent.preventDefault();
}
settings.decimalError = true;
settings.onError.call(element, settings);
return false;
}
/** Any idea on how to allow only one negative sign at the beginning?
write regex code here **/
if (settings.decimalAllow) {
regex = (settings.negativeAllow) ? /[0-9]|\-|\./ : /[0-9]|\./;
} else {
regex = (settings.negativeAllow) ? /[0-9]|\-/ : /[0-9]/;
}
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault();
}
settings.afterKeypressAction.call(element, settings);
}
function triggerBlurAction(evt, element) {
settings.beforeBlurAction.call(element, settings);
var inputValue = $(element).val(),
parsedValue = (settings.decimalAllow) ? parseFloat(inputValue) : parseInt(inputValue, 10);
if (isNaN(parsedValue)) {
$(element).val('');
} else if (settings.negativeAllow) {
$(element).val(parsedValue);
} else {
$(element).val(Math.abs(parsedValue));
}
settings.afterBlurAction.call(element, settings);
settings.onComplete.call(element, settings);
}
};
})(jQuery);
$(".numberTextBox").inputNumericTextBox({
negativeAllow: true,
decimalAllow: true,
beforeKeypressAction: function(e) {
console.log(this);
console.log(e);
console.log('before key');
},
afterKeypressAction: function(e) {
console.log(this);
console.log(e);
console.log('after key');
},
beforeBlurAction: function(e) {
console.log(this);
console.log(e);
console.log('before blur');
},
afterBlurAction: function(e) {
console.log(this);
console.log(e);
console.log('after blur');
},
onError: function(e) {
console.log(this);
console.log(e);
console.log('on error');
if (e.decimalError) {
alert('More than one decimal number is not allowed');
} else if (e.negativeSignError) {
alert('More than one negative sign is not allowed.\n You can only use negative at the start');
}
},
onComplete: function(e) {
console.log(this);
console.log(e);
console.log('on complete');
},
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<input id="firstbox" type="text" class="numberTextBox" />
<input id="secondbox" type="text" class="numberTextBox" />
</body>
I thought I should try myself. what I did is put all the content of the plugin to another private function. and call the function in a loop to initialize every element separately. that way I achieved my goal and all events are working properly. and few more to support single negative sign. now it's proper input number textbox.
check it out here https://jsfiddle.net/mzhe2rde/6/
//JQuery Custom Plugin inputNumericTextBox
(function($) {
"use strict";
var inputNumericTextBox = function(element, options) {
var previous_value_set = false;
var previous_value = '';
var defaults = {
negativeAllow: true,
decimalAllow: true,
decimalError: false,
startNegativeSignError: false,
multipleNegativeSignError: false,
beforeKeypressAction: function() {},
afterKeypressAction: function() {},
beforeKeyupAction: function() {},
afterKeyupAction: function() {},
beforeBlurAction: function() {},
afterBlurAction: function() {},
onError: function() {},
onInitializationComplete: function() {},
};
var settings = $.extend({}, defaults, options);
$(element).on('keypress', function(e) {
//console.log("keypress");
triggerKeypressAction(e, element);
});
$(element).on('keyup', function(e) {
//console.log("keyup");
triggerKeyupAction(e, element);
});
$(element).on('blur', function(e) {
//console.log("blur");
triggerBlurAction(e, element);
});
settings.onInitializationComplete.call(element, settings);
function triggerKeypressAction(evt, element) {
settings.beforeKeypressAction.call(element, settings);
var regex;
var theEvent = evt || window.event;
var key = String.fromCharCode(theEvent.keyCode || theEvent.which);
if (/\./.test(key) && /\./.test($(element).val())) {
theEvent.returnValue = false;
if (theEvent.preventDefault) {
theEvent.preventDefault();
}
settings.decimalError = true;
settings.onError.call(element, settings);
settings.afterKeypressAction.call(element, settings);
settings.decimalError = false;
return false;
}
if (/-/.test(key) && /-/.test($(element).val())) {
theEvent.returnValue = false;
if (theEvent.preventDefault) {
theEvent.preventDefault();
}
settings.multipleNegativeSignError = true;
settings.onError.call(element, settings);
settings.afterKeypressAction.call(element, settings);
settings.multipleNegativeSignError = false;
return false;
}
if (/-/.test(key)) {
previous_value_set = true;
previous_value = $(element).val();
}
if (settings.decimalAllow) {
regex = (settings.negativeAllow) ? /[0-9]|-|\./ : /[0-9]|\./;
} else {
regex = (settings.negativeAllow) ? /[0-9]|-/ : /[0-9]/;
}
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault();
}
settings.afterKeypressAction.call(element, settings);
}
function triggerKeyupAction(evt, element) {
settings.beforeKeyupAction.call(element, settings);
if (settings.negativeAllow && previous_value_set) {
if (!(/^-.*/.test($(element).val()))) {
$(element).val(previous_value);
settings.startNegativeSignError = true;
settings.onError.call(element, settings);
settings.startNegativeSignError = false;
}
}
previous_value_set = false;
previous_value = '';
settings.afterKeyupAction.call(element, settings);
}
function triggerBlurAction(evt, element) {
settings.beforeBlurAction.call(element, settings);
var inputValue = $(element).val(),
parsedValue = (settings.decimalAllow) ? parseFloat(inputValue) : parseInt(inputValue, 10);
if (isNaN(parsedValue)) {
$(element).val('');
} else if (settings.negativeAllow) {
$(element).val(parsedValue);
} else {
$(element).val(Math.abs(parsedValue));
}
settings.afterBlurAction.call(element, settings);
}
return;
};
if (!jQuery.fn.inputNumericTextBox) {
jQuery.fn.inputNumericTextBox = function(options) {
return this.each(function() {
inputNumericTextBox(this, options);
return this;
});
};
}
})(jQuery);
$(".numberTextBox").inputNumericTextBox({
negativeAllow: true,
decimalAllow: true,
beforeKeypressAction: function(e) {
//console.log(this);
//console.log(e);
//console.log('before keypress');
},
afterKeypressAction: function(e) {
//console.log(this);
//onsole.log(e);
//console.log('after keypress');
},
beforeKeyupAction: function(e) {
//console.log(this);
//onsole.log(e);
//console.log('before keyup');
},
afterKeyupAction: function(e) {
//console.log(this);
//onsole.log(e);
//console.log('after keyup');
},
beforeBlurAction: function(e) {
//console.log(this);
//console.log(e);
//console.log('before blur');
},
afterBlurAction: function(e) {
//console.log(this);
//console.log(e);
//console.log('after blur');
},
onError: function(e) {
//console.log(this);
//console.log(e);
//console.log('on error');
if (e.decimalError) {
alert('More than one decimal number is not allowed');
} else if (e.multipleNegativeSignError) {
alert('More than one negative sign is not allowed.');
} else if (e.startNegativeSignError) {
alert('You can only use one negative sign at the start');
}
},
onInitializationComplete: function(e) {
//console.log(this);
//console.log(e);
//console.log('on complete');
},
});
/* Last initialization settings will take the precedence but events will trigger on all initialization
* You shouldn't initialize more than one on a single element because it will create more object and it will take some memory to store it.
* It's their to support large environment */
/* This is an example of last initialization or initialization more than one */
/*
$(".numberTextBox").inputNumericTextBox();
var n = $(".numberTextBox").inputNumericTextBox({
negativeAllow: false,
decimalAllow: true
});
console.log(n);*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<input type="text" class="numberTextBox" />
<input type="text" class="numberTextBox" />
</body>

DevExtreme DataGrid onRowDblClick

I want to implement an onRowDblClick event for the DevExtreme DataGrid.
I need this Event for multiple grids so I would like to implement this for the DataGrid for general.
I was thinking about overriding the onClick action and check for a double click or extend the DataGrid with an onRowDblClick Action but i have no idea how to implement this.
Please advise a way to do this functionality.
OK, finally I implemented an addRowDblClick function which looks like this:
var clickTimer, lastRowClickedId;
function addRowDblClick(id, dblClickFunc) {
$("#" + id).dxDataGrid({
onRowClick: function (e) {
//OBTAIN YOUR GRID DATA HERE
var grid = $("#" + id).dxDataGrid('instance');
var rows = grid.getSelectedRowsData();
if (clickTimer && lastRowCLickedId === e.rowIndex) {
clearTimeout(clickTimer);
clickTimer = null;
lastRowCLickedId = e.rowIndex;
//YOUR DOUBLE CLICK EVENT HERE
if (typeof dblClickFunc == 'function')
dblClickFunc();
} else {
clickTimer = setTimeout(function () { }, 250);
}
lastRowCLickedId = e.rowIndex;
}
});
}
And at the DataGrid I called an function OnContentReady where I call this function with the Id and the function I want to call when I double click.
addRowDblClick('dxDataGrid', showDetail);
I that work with this :
$("#grdMain").dxDataGrid({
....
onRowPrepared:function(event){
$(event.rowElement).on('dblclick', function(){
console.log('row dblclicked');
}).on('remove', function(){
//on remove event in jquery ui libraries or
// https://stackoverflow.com/questions/29255801/jquery-on-remove-not-working-parent-node-fire-empty
$(this).off('dblclick remove');
})
}
})
I did this and worked pretty well (I followed this answer)
var clickTimer, lastRowCLickedId;
$("#grdMain").dxDataGrid({
...
onRowClick: function (e) {
//OBTAIN YOUR GRID DATA HERE
var grid = $("#grdMain").dxDataGrid('instance');
var rows = grid.getSelectedRowsData();
if (clickTimer && lastRowCLickedId === e.rowIndex) {
clearTimeout(clickTimer);
clickTimer = null;
lastRowCLickedId = e.rowIndex;
//YOUR DOUBLE CLICK EVENT HERE
alert('double clicked!');
} else {
clickTimer = setTimeout(function () { }, 250);
}
lastRowCLickedId = e.rowIndex;
}
});

Cannot select a dynamically added list item until it is clicked

I have written a small JQuery plugin that creates a dropdown box based on bootstrap. I have written it to where a data attribute supplies a url that produces the list items. After the ajax call, Jquery loops through the list items and inserts them into the dropdown menu. Here is what I do not understand, the plugin takes a div with the class of .combobox and appends the required html to make the combobox. It uses two functions, _create() and _listItems(). _create() actually adds the html and calls on _listItems() to make the ajax call and it returns the list items to be appended. Looks like this:
;(function ( $, window, document, undefined ) {
var Combobox = function(element,options) {
this.$element = $(element);
this.$options = $.extend({}, $.fn.combobox.defaults, options);
this.$html = {
input: $('<input type="text" placeholder="[SELECT]" />').addClass('form-control'),
button: $('<div id="test"/>').addClass('input-group-btn')
.append($('<button />')
.addClass('btn btn-default input-sm')
.append('<span class="caret"></span>'))
}
this.$list_type = this.$element.attr('data-type');
this.$url = this.$element.attr('data-url');
this.$defaultValue = this.$element.attr('data-default');
this._create();
this.$input = this.$element.find('input');
this.$button = this.$element.find('button');
this.$list = this.$element.find('ul')
this.$button.on('click',$.proxy(this._toggleList,this));
this.$element.on('click','li',$.proxy(this._itemClicked,this));
this.$element.on('mouseleave',$.proxy(this._toggleList,this));
if(this.$defaultValue) {
this.selectByValue(this.$defaultValue);
}
}
Combobox.prototype = {
constructor: Combobox,
_create: function() {
this.$element.addClass('input-group input-group-sm')
.append(this.$html.input)
.append(this._listItems())
.append(this.$html.button);
},
_itemClicked: function(e){
this.$selectedItem = $(e.target).parent();
this.$input.val(this.$selectedItem.text());
console.log(this.$element.find('[data-value="W"]'))
this._toggleList(e);
e.preventDefault();
},
_listItems: function() {
var list = $('<ul />').addClass('dropdown-menu');
$.ajax({
url: this.$url,
type: 'POST',
data: {opt: this.$list_type},
success:function(data){
$.each(data,function(key,text){
list.append($('<li class="listObjItem" data-value="'+text.id+'">'+text.value+'</li>'));
})
}
})
return list
},
selectedItem: function() {
var item = this.$selectedItem;
var data = {};
if (item) {
var txt = this.$selectedItem.text();
data = $.extend({ text: txt }, this.$selectedItem.data());
}
else {
data = { text: this.$input.val()};
}
return data;
},
selectByValue: function(value) {
var selector = '[data-value="'+value+'"]';
this.selectBySelector(selector);
},
selectBySelector: function (selector) {
var $item = this.$element.find(selector);
if (typeof $item[0] !== 'undefined') {
this.$selectedItem = $item;
this.$input.val(this.$selectedItem.text());
}
else {
this.$selectedItem = null;
}
},
enable: function () {
this.$input.removeAttr('disabled');
this.$button.children().removeClass('disabled');
this.$button.on('click',$.proxy(this._toggleList,this));
},
disable: function () {
this.$input.attr('disabled', true);
this.$button.children().addClass('disabled');
this.$button.off('click',$.proxy(this._toggleList,this));
},
_toggleList: function(e) {
if(e.type == 'mouseleave') {
if(this.$list.is(':hidden')) {
return false;
} else {
this.$list.hide();
}
} else {
this.$list.toggle();
e.preventDefault();
}
}
}
$.fn.combobox = function (option) {
return this.each(function () {
if (!$.data(this, 'combobox')) {
$.data(this, 'combobox',
new Combobox( this, option ));
}
});
};
$.fn.combobox.defaults = {};
$.fn.combobox.Constructor = Combobox;
})( jQuery, window, document );
The problem is that after the items are appended to the DOM, everything is selectable accept the list items. I currently have an .on() statement that binds the click event with the list item. To test this out I have used console.log(this.$element.find('[data-value="W"]') and it does not return an element, however if I place that same console log in the click callback of the list item it will return the element and it is selectable. Am I doing something wrong?
EDIT
I have pasted the entire plugin to save on confusion.

kendoui angular grid selection event

I am trying to handle a selection event from a KendoUI Grid in AngularJS.
I have got my code working as per below. However it feels like a really nasty way of having to get the data for the selected row. Especially using _data. Is there a better way of doing this? Have I got the wrong approach?
<div kendo-grid k-data-source="recipes" k-selectable="true" k-sortable="true" k-pageable="{'refresh': true, 'pageSizes': true}"
k-columns='[{field: "name", title: "Name", filterable: false, sortable: true},
{field: "style", title: "Style", filterable: true, sortable: true}]' k-on-change="onSelection(kendoEvent)">
</div>
$scope.onSelection = function(e) {
console.log(e.sender._data[0].id);
}
please try the following:
$scope.onSelection = function(kendoEvent) {
var grid = kendoEvent.sender;
var selectedData = grid.dataItem(grid.select());
console.log(selectedData.id);
}
Joining the party rather late, there is a direct way to do it without reaching for the grid object:
on the markup:
k-on-change="onSelection(data)"
in the code:
$scope.onSelection = function(data) {
// no need to reach the for the sender
}
note that you may still send selected, dataItem, kendoEvent or columns if needed.
consult this link for more details.
Directive for two-way binding to selected row. Should be put on the same element
as kendo-grid directive.
Typescript version:
interface KendoGridSelectedRowsScope extends ng.IScope {
row: any[];
}
// Directive is registered as gridSelectedRow
export function kendoGridSelectedRowsDirective(): ng.IDirective {
return {
link($scope: KendoGridSelectedRowsScope, element: ng.IAugmentedJQuery) {
var unregister = $scope.$parent.$on("kendoWidgetCreated", (event, grid) => {
if (unregister)
unregister();
// Set selected rows on selection
grid.bind("change", function (e) {
var selectedRows = this.select();
var selectedDataItems = [];
for (var i = 0; i < selectedRows.length; i++) {
var dataItem = this.dataItem(selectedRows[i]);
selectedDataItems.push(dataItem);
}
if ($scope.row != selectedDataItems[0]) {
$scope.row = selectedDataItems[0];
$scope.$root.$$phase || $scope.$root.$digest();
}
});
// Reset selection on page change
grid.bind("dataBound", () => {
$scope.row = null;
$scope.$root.$$phase || $scope.$root.$digest();
});
$scope.$watch(
() => $scope.row,
(newValue, oldValue) => {
if (newValue !== undefined && newValue != oldValue) {
if (newValue == null)
grid.clearSelection();
else {
var index = grid.dataSource.indexOf(newValue);
if (index >= 0)
grid.select(grid.element.find("tr:eq(" + (index + 1) + ")"));
else
grid.clearSelection();
}
}
});
});
},
scope: {
row: "=gridSelectedRow"
}
};
}
Javascript version
function kendoGridSelectedRowsDirective() {
return {
link: function ($scope, element) {
var unregister = $scope.$parent.$on("kendoWidgetCreated", function (event, grid) {
if (unregister)
unregister();
// Set selected rows on selection
grid.bind("change", function (e) {
var selectedRows = this.select();
var selectedDataItems = [];
for (var i = 0; i < selectedRows.length; i++) {
var dataItem = this.dataItem(selectedRows[i]);
selectedDataItems.push(dataItem);
}
if ($scope.row != selectedDataItems[0]) {
$scope.row = selectedDataItems[0];
$scope.$root.$$phase || $scope.$root.$digest();
}
});
// Reset selection on page change
grid.bind("dataBound", function () {
$scope.row = null;
$scope.$root.$$phase || $scope.$root.$digest();
});
$scope.$watch(function () { return $scope.row; }, function (newValue, oldValue) {
if (newValue !== undefined && newValue != oldValue) {
if (newValue == null)
grid.clearSelection();
else {
var index = grid.dataSource.indexOf(newValue);
if (index >= 0)
grid.select(grid.element.find("tr:eq(" + (index + 1) + ")"));
else
grid.clearSelection();
}
}
});
});
},
scope: {
row: "=gridSelectedRow"
}
};
}
A quick example of how to do this with an angular directive.
Note here that I'm getting the reference to the underlying kendo grid through the click event and the DOM handle.
//this is a custom directive to bind a kendo grid's row selection to a model
var lgSelectedRow = MainController.directive('lgSelectedRow', function () {
return {
scope: {
//optional isolate scope aka one way binding
rowData: "=?"
},
link: function (scope, element, attributes) {
//binds the click event and the row data of the selected grid to our isolate scope
element.bind("click", function(e) {
scope.$apply(function () {
//get the grid from the click handler in the DOM
var grid = $(e.target).closest("div").parent().data("kendoGrid");
var selectedData = grid.dataItem(grid.select());
scope.rowData = selectedData;
});
});
}
};
});
I would suggest to use like this, I was also getting undefined when I upgraded my application from angular 7 to 15. Now I get event details like this
public selectedRowChangeAction(event:any): void {
console.log(event.selectedRows[0].dataItem.Id); }
event has selected Row at its 0 index and you can have dataItem as first object and then you can have all object details whatever you have for example Id, Name,Product details whatever you want to select, Something like you can see in picture

Categories

Resources