I am trying to put a button in the cells of one of the columns and do something when it's clicked.
For example I add these lines to the SlickGrid example 1 (http://mleibman.github.io/SlickGrid/examples/example1-simple.html)
First to the column array I add:
{id: "Report", name: "Report", field: "Report", width: 40, sortable: true, formatter:reportFormatter}
then I add:
function reportFormatter(row, cell, value, columnDef, dataContext) {
return "<input type='button' value='show' id='reportBtn'/>";
}
$('#reportBtn').click(function() {
alert("hello");
});
The buttons appear in the cells but the click event is not being called !
I must be doing something wrong but can't for the life of me figure it out
can anyone help ?
Thanks!
slick.formatters.js
...
"btnForm": buttonsFormatter // add Slick.Formatters
..
function buttonsFormatter(row, cell, value, columnDef, dataContext) {
return "<input type='button' value='"+value+"' id='btnForm' value2='"+row+"' value3='"+cell+"' onClick='fnBtnClick(this);'/>";
}
add your html Script
function fnBtnClick( objBtn ){
alert( "row::[" + objBtn.value2 + "]\n\ncell::[" + objBtn.value3 + "]" );
}
you should use the grid events not button event like below ,
will call the onclick event of the grid ,
check if the clicked field is your button one
do your action
grid.onClick.subscribe(function (e, args) {
//check if your button was clicked
if ($(e.target).hasClass("btn")) {
var item = dataView.getItem(args.row);
///do your action
}
});
Use the precompiled template slick grid example. Add the property eg. ImageTrial, and in the data structure fill the property with the dynamic input button.
<script type=" " id="testtemplate">
<div class="test">
<b><%=ImageTrial%></b>
<b><%=ImageTrial2%></b>
</div>
dataForCell["ImageTrial"] = "<button type=\"button\" onclick=\"alert('a " + 1 + "')\">s</button>";
dataForCell["ImageTrial2"] = "<button type=\"button\" onclick=\"alert('b " + 2 + "')\">b</button>";
Good Luck
Related
I'm using tom-select on my django form. On the form I also make a reset button to clear all input fields. All input values are cleared when I click the button, except the one using tom-select.
form.py
class ItemInputForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ItemInputForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Row(
....
Column('item', css_class = 'col-md-4'),
css_class = 'row'
),
....
Div(
HTML('<button type="submit" class="btn btn-danger col-md-4 me-4"><i class="fa-solid fa-print"></i> Print</button>'),
HTML('<button type="reset" class="btn btn-warning col-md-4"><i class="fa-solid fa-rotate-left"></i> Reset</button>'),
css_class = 'text-center'
),
....
tom-select on the template
$(document).ready(function()
{
var item_select = new TomSelect("#id_item",{
create: false,
placeholder: 'Search',
valueField: 'value',
searchField: 'text',
maxItems: 1,
closeAfterSelect: true,
render: {
option: function(data, escape) {
return '<div>' + '<span class="text">' + escape(data.text) + '</span>' + '<span class="value">' + escape(data.value) + '</span>' + '</div>';
},
item: function(data, escape) {
return '<div title="' + escape(data.value) + '">' + escape(data.text) + '</div>';
},
},
});
item_select.clear();
When I refresh the page, the input field is clear because of item_select.clear(), but it didn't work if I want to clear with reset button. How to clear the tom-select input with reset button?
I was confronted to the same issue, and here is my solution.
I enable tom-select for each HTML element having the tom-select-enabled class.
I use the tomselected class to fetch all tom-select enabled elements of a form on reset, and call the tomselect.clear() method.
document.addEventListener('DOMContentLoaded', function() {
// Select all elements having the class 'tom-select-enabled', and enable TomSelect for these elements.
document
.querySelectorAll(".tom-select-enabled")
.forEach((tomSelectElement) => {
console.log(`Enabling tom-select for #${tomSelectElement.id}`);
var tomSelectItem = new TomSelect(tomSelectElement, {
plugins: {
clear_button: { title: "Vider" }
},
create: false,
persist: false
});
});
// Clear all TomSelect instances of forms on reset.
document.querySelectorAll("form").forEach((formElement) => {
formElement.addEventListener("reset", (event) => {
event.target
.querySelectorAll(".tomselected")
.forEach((tomselectedElement) => {
tomselectedElement.tomselect.clear();
});
});
});
});
As far as I could find, the reset event is not triggered for the element once TomSelect is instantiated.
Another issue is that the clear() method visually empty the tom-select field, but if the initial select field has a selected="selected" <option>, it set the select value to its selected option default.
If filed two issues on the subject:
Tom Select enabled field does not react to form reset events #544.
clear() method empty the visible tom-select field, but set the select field to the default selected option #545.
I've found some tips on how to clean my code in How to clear existing (dynamically created) instances of Tom-Select #170.
My objective:
Filling in the 'performer-payments' table dynamically with JS/Jquery
For each (dynamically added) row in the table, one of the data cells contains a dropdown box.
This dropdown box should, when a certain option is selected, make visible another dropdown box (in the same cell). Otherwise, this second dropdown should be invisible.
Elsewhere I am accomplishing the hide/show dynamics by means of a toggleVisible function, which simply adds custom classes which is marked by css to hide or show the element.
The relevant code:
The table I want to populate:
<table id='performer-payments' class='performer-profile payments-table'>
<tr>
<th> Period </th>
<th> Amount </th>
<th> Paid? </th>
</tr>
</table>
The code that populates the table:
for (period in data['Performers'][performer]['Payments']) {
var amount = utils.calcPerformerCut(data, performer, period);
var row = "<tr>";
row += "<td> " + period + " </td>";
row += "<td> " + amount + " $ </td>";
row += "<td>";
row += "<div class='performer-profile payment-status'>";
row += data['Performers'][performer]['Payments'][period];
row += "</div>";
row += "<select id='payment-status-" + performer + "-" + period + "' class='perfomer-profile hidden-onload displayNone payment-status-menu'>";
row += "<option value='paid'>Paid</option>";
row += "<option value='unpaid'>Unpaid</option>";
row += "<option value='transfer'>Transfer to...</option>";
row += "</select>";
row += "<select id='payment-transfer-period-" + performer + "-" + period + "' class='performer-profile hidden-onload displayNone payment-period-menu'>";
for (var i=0; i < data['Periods'].length; i++) {
row += "<option value='" + period + "'>" + period + '</option>';
}
row += "</select>";
row += "</td>";
row += "</tr>";
$('#performer-payments').append(row);
$('#performer-payments').on('change', {perf: performer, per: period}, function (even) {
if (even.target.value == 'transfer') {
utils.toggleVisible($('#payment-transfer-period-' + even.data.perf + '-' + even.data.per), true);
} else {
utils.toggleVisible($('#payment-transfer-period-' + even.data.perf + '-' + even.data.per), false);
}
});
}
For reference, the code that toggles visibility:
exports.toggleVisible = function (selector, visible) {
if (visible) {
selector.removeClass('displayNone').addClass('displayBlock');
} else {
selector.removeClass('displayBlock').addClass('displayNone');
}
}
There are (at least) two issues with this:
The #payment-transfer-period-... select box is never displayed, even when the 'transfer' option is chosen in the first select box. From debugging efforts it seems to me that it could be that the #payment-transfer-period-.. for some reason is not a valid object yet, or something like that.
(Obviously, really), the on-change event is triggered N times (N=number of periods) because I am just telling the program to trigger whenever something in the table changes. I would like it to trigger only for the relevant dropdown, but when I tried adding the #payment-status-... as a selector to the .on() function, it made it never trigger.
Note: I welcome feedback on this in general - I am an experienced programmer but have very little experience with HTML/JS/Jquery. Further, I have decided to not use templates for this project since I am trying to learn the basics, so if you get pancreatitis from seeing the way I am 'dynamically' adding the rows to the table, I apologize but it is partly intentional.
Other than that, please ask for clarifications if something is not clear here.
Edit: Here is the relevant part of the data structure:
data = {
'Performers': {
'Dira Klaggen': {
'Payments': {
'Q1': 'Paid',
'Q2': 'Paid',
'Q3': 'Unpaid'
},
},
'Holden Bolden': {
'Payments': {
'Q2': 'Transferred to Q3',
'Q3': 'Unpaid'
}
},
'Manny Joe': {
'Payments': {
'Q1': 'Paid',
'Q2': 'Unpaid',
'Q3': 'Unpaid',
}
}
},
'Periods': [
'Q1',
'Q2',
'Q3'
]
}
You do not attach the change handler to the right element. I should be the first select in the row... Instead of the whole table.
Try this change handler:
$('#performer-payments').find('#payment-status-' + performer + '-' + period).on('change', function(){
if ($(this).val() == 'transfer') {
$(this).next('select').show();
} else {
$(this).next('select').hide();
}
});
Second approach:
You could simplify that by using a class instead of a "complicated" unique id for the first select.
Say you use the class "payment-status":
The handler would be:
$('#performer-payments').on('change', '.payment-status', function(){
if ($(this).val() == 'transfer') {
$(this).next('select').show();
} else {
$(this).next('select').hide();
}
});
And this handler can be out of the row appending loop because it uses delegation.
Let's clean up your code by doing the following things:
Use classes instead of ugly IDs.
Use data-attributes or hidden input fields to hold extra information.
Use event delegation to bind dynamically-created elements. Inside the event handler, use tree traversal methods to limit the scope of the search based on the current element this.
Let's apply these things.
Build each row like this. {PLACEHOLDER} is where you put your variable stuff like you have in your code.
<tr>
<td>{PERIOD}</td>
<td>{AMOUNT} $ </td>
<td>
<div class='performer-profile payment-status'>
{SOMETHING-RELATING-TO-PERFORMER-PAYMENT-PERIOD}
</div>
<!-- remove ID -->
<!-- store performer and period in data-attributes -->
<select class='perfomer-profile hidden-onload displayNone payment-status-menu' data-performer='{PERFORMER}' data-period='{PERIOD}'>
<option value='paid'>Paid</option>
<option value='unpaid'>Unpaid</option>
<option value='transfer'>Transfer to...</option>
</select>
<!-- remove ID -->
<select class='performer-profile hidden-onload displayNone payment-period-menu'>
<option value='{PERIOD}'>{PERIOD}</option>
<option value='{PERIOD}'>{PERIOD}</option>
<option value='{PERIOD}'>{PERIOD}</option>
<!-- etc -->
</select>
</td>
</tr>
In your JavaScript, create a delegated event handler. Note the syntax.
$(function () {
// ...
for (period in data['Performers'][performer]['Payments']) {
// build and append row
}
// create delegated event handler once and outside FOR loop
$(document).on('change', '.payment-status-menu', function () {
// get the current status menu
var statusMenu = $(this);
// find its related period menu
var periodMenu = statusMenu.closest('tr').find('.payment-period-menu');
// toggle its visibility
periodMenu.toggle(this.value == 'Transfer');
// of course, this could be a one-liner
//$(this).closest('tr').find('.payment-period-menu').toggle(this.value == 'Transfer');
});
});
It doesn't seem like you need (2.) but if you do, within the event handler, use statusMenu.data('performer') or statusMenu.data('period') to get its performer and period values. You could also do this.dataset.performer or this.dataset.period.
I have a table where in each row for each id we have 'Client' column. When a user clicks on the row he is able to change client. I am using jquery.dialog for this operation. When a dialog appears the user sees a dropdownlist with Clients. How I can make that after dialog appears, the user sees the current client as the selected item in the dropdown? I've tried as below:
onDblClickRow: function (row, $element) {
$.getJSON('/ManageProjects/GetAvaibleClients/', function (clients) {
if (clients.length == 0) {
$('#clientNameEdit').empty();
$('#clientNameEdit').append('<option value="0">Tasks</option>');
}
$.each(clients, function (index, clientt) {
$('#clientNameEdit').append("<option value='" + clientt.Value + "'>" + clientt.Text + "</option>");
});
})
var currentClient = row.clientName; // Client name from Row
$('#clientNameEdit select').val(currentClient); // Tried to set like that
}
but doesn't work
The value passed in to .val needs to be the clientt.Value and not the text name.
if you dont have the clientt.Value, then try something like:-
$("#clientNameEdit option[text=" + currentClient + "]").attr("selected", true);
And bring the setting of the select inside of the success function.
The following alteration to your code snippet should do the trick:
onDblClickRow: function (row, $element) {
$.getJSON('/ManageProjects/GetAvaibleClients/', function (clients) {
if (clients.length == 0) {
$('#clientNameEdit').empty();
$('#clientNameEdit').append('<option value="0">Tasks</option>');
}
$.each(clients, function (index, clientt) {
$('#clientNameEdit').append("<option value='" + clientt.Value + "'>" + clientt.Text + "</option>");
});
var currentClient = row.clientName; // Client name from Row
$('#clientNameEdit').val(currentClient); // Tried to set like that but doesn't work
});
As indicated above, if you do the currentClient = row.clientName outside the success of the ajax call, it will probably fire before the dropdown is populated and therefore not have any effect.
Secondly the jQuery selector '#clientNameEdit select' should only be '#clientNameEdit' as it refer to the dropdown itself and not it's parent.
I have a table of data where users can edit the information by a click. The click will replace the number data with an input text field that will allow the users to submit their edits. I've included a "cancel" link where once clicked, the input field will disappear and the data text reappears. However, if I clicked to edit multiple rows and cancel it, the data text will reappear as the first row that I clicked.
For example, my table of data looks like this
Ref No. | Container No.
0006 | OLKI2940
0005 | KL2223KL
0004 | PPO80596
0003 | JLJ93459
If I clicked to edit Container # "OLKI2940", I cancel it and "OLKI2940" will reappear fine. However, if I clicked to edit the second row Container # "KL2223KL" and cancel, the Container # "OLKI2940" will appear. So it's copying the first row that I clicked. How do I get it for the right container number to appear?
My html as follow:
// this is in a loop
<tr>
<td>{{ refnum }}</td>
<td id="{{ ctrnum }}">{{ ctrnum }}</td>
</tr>
My JS:
// editing container no
$('#containers').delegate("a.ctrnoedit","click", function() {
var index = $(this).closest("td").attr("id");
var html = "<form id='editctrno' method='post'><input name='ctrnum' type='text' value='"+index+"'>" +
"<br><button type='submit'>Update</button> <a href='#' id='canceledit'>Cancel</a></form>";
$(this).closest("td").html(html);
$('#containers').delegate("a#canceledit", "click", function() {
$(this).closest("#editctrno").html("<a href='#' class='ctrnoedit'>"+index+"</a>");
})
})
JS fiddle example:
http://jsfiddle.net/9Lsgw2ve/1/
although your way of coding violates the rules of html by generating duplicated ids, this is a Working Demo
var index='';
// editing container no
$('#containers').delegate("a.ctrnoedit", "click", function () {
index = $(this).closest("td").attr("id");
var html = "<form id='editctrno' method='post'><input name='ctrnum' type='text' value='" + index + "'>" +
"<br><button type='submit'>Update</button> <a href='#' id='canceledit'>Cancel</a></form>";
$(this).closest("td").html(html);
$('#containers').delegate("a#canceledit", "click", function () {
$(this).closest("#editctrno").html("<a href='#' class='ctrnoedit'>" + index + "</a>");
})
})
you just need to define index out of the click function
also if you wanna get the exact same values as it was in the links then try this:
DEMO
var index='';
// editing container no
$('#containers').delegate("a.ctrnoedit", "click", function () {
index = $(this).closest("td").children('a').html();
var html = "<form id='editctrno' method='post'><input name='ctrnum' type='text' value='" + index + "'>" +
"<br><button type='submit'>Update</button> <a href='#' id='canceledit'>Cancel</a></form>";
$(this).closest("td").html(html);
$('#containers').delegate("a#canceledit", "click", function () {
$(this).closest("#editctrno").html("<a href='#' class='ctrnoedit'>" + index + "</a>");
})
})
I am using javascript to create html page , but not able to call some function on button click .
var alernative = "plot1";
var buttonvalue= "mybutton";
function callme()
{alert("hello");}
$('#' + alernative).html('<div><input style="float:right;" type="button" value="' + buttonvalue+ '" onclick="' + callme() + '";></div>');
In above code , creating a button and giving its value and calling function onclick of button , but when the page loads it shows alert (that should not happen) and it is not alerting on button click .
Hoping for Suggestion or some help .
You need to pass the function name as a part of the string:
$('#' + alernative).html('<div><input style="float:right;" type="button" value="' + buttonvalue+ '" onclick="callme();"></div>');
It is a bad practice to write HTML with strings, DOM exists for one reason!
var input = $('<input/>', {
type: "button",
style: "float: right",
value: buttonValue
}),
element = $('<div/>').append(input);
input.click(function () {
callme();
});
$('#test').html(element);