I have data below and I want to pass two variables (id, name) in the columns.render function in Datatables.
What I have now is only pass the id in the render function.
I also want to pass name in the render function.
Thanks.
const myData = [
{ id: 2, name: "book" },
{ id: 5, name: "song" },
];
$("#example").DataTable({
data: myData,
columns: [
{
targets: 1,
data: "id",
render: function (data, type, row, meta) {
return (
"<button class='btn btn-default' data_id='" +
data + //id is passed to here
"'>" +
"name" + //the name I want to pass to here.
"</button>"
);
},
},
],
});
You can do it using the row parameter of render function.
const myData = [
{ id: 2, name: "book" },
{ id: 5, name: "song" },
];
$("#example").DataTable({
data: myData,
columns: [
{
targets: 1,
data: "id",
render: function (data, type, row, meta) {
return (
"<button class='btn btn-default' data_id='" +
data + //id is passed to here
"'>" +
row.name + //get the name using row parameter
"</button>"
);
},
},
],
});
More details about render function can be found at https://datatables.net/reference/option/columns.render
Related
I am building a datatable and have added a checkbox dropdown for adding/removing columns in the table. Everything works fine except it is not rerendering the table until I click on one of the header titles.
At the top of the function component, I am setting the state as follows:
const [formColumns, setDisplayFields] = useState(formFields);
formFields is retrieved from a file and is formatted as below. It's an array of JSON column objects that looks like this:
[id: {
name: 'id',
label: 'Patient Id',
displayColumn: false,
displayOrder: 1,
},
firstName: {
name: 'firstName',
label: 'First Name*',
requiredErrorMsg: 'First name is required',
displayColumn: true,
displayOrder: 2,
},
middleName: {
name: 'middleName',
label: 'Middle Name',
displayColumn: false,
displayOrder: 0,
},
lastName: {
name: 'lastName',
label: 'Last Name*',
requiredErrorMsg: 'Last name is required',
displayColumn: true,
displayOrder: 0,
},
suffix: {
name: 'suffix',
label: 'Suffix',
displayColumn: false,
displayOrder: 0,
},
dob: {
name: 'dob',
label: 'Date of Birth*',
requiredErrorMsg: 'Birth date is required',
invalidErrorMsg: 'This is not a valid date',
displayColumn: true,
displayOrder: 3,
},
organization: {
name: 'organization',
label: 'Organization',
displayColumn: false,
displayOrder: 4,
},
]
There are actually more columns, but this should suffice for describing what I'm doing. The 'displayColumn' element is changed in an onChange event in the same component that displays the table (passes it as a prop into checkbox menu). Here's the onchange:
/**
* handleCheckboxSelect
* #param {string} colname
*/
var handleCheckboxSelect = (colname) =>
{
//return the index of the column checked/unchecked
var icol = getColumnIndex(formColumns, colname);
console.log('FOUND COLINDEX = ' + icol + '.');
if (icol > -1) {
//toggle the display parameter
formColumns[icol].displayColumn = (formColumns[icol].displayColumn === false);
//store the updated column in the column list
setDisplayFields(formColumns);
}
else {
console.log('checkbox colname = ' + colname);
}
}
As you can see, I am using state as required, and any time state changes, it should force a re-render. However, it's not. Is it because I am using an array of objects? If I pass a single column back and stroe that in state, would that fix the issue? I'm stumped. Any help would be greatly appreciated!
You are setting same formColumns reference on setDisplayFields which will not trigger re-render of the component. Try to copy formColumns to a new array and make changes on that array.
Try this -
var handleCheckboxSelect = (colname) =>
{
//create new array from existing one
let newColumns = [...formColumns];
var icol = getColumnIndex(newColumns, colname);
console.log('FOUND COLINDEX = ' + icol + '.');
if (icol > -1) {
//toggle the display parameter
newColumns[icol].displayColumn = (newColumns[icol].displayColumn === false);
//store the updated column in the column list
setDisplayFields(newColumns);
}
else {
console.log('checkbox colname = ' + colname);
}
}
I'm having a hard time to structure the list location for items array in order to access name attribute in search.js
Below is the nested JSON structure:
{
menus: [
{
name: "Summer ",
url: "/menus/2",
items: [
{
name: "man o man", //this is what I'm trying to access
url: "/menus/2/items/7"
}
]
]
}
So far I've tried in search.js:
document.addEventListener("turbolinks:load", function() {
$input = $("[data-behavior='autocomplete']")
var options = {
getValue: "name",
url: function(phrase) {
data = "/search.json?q=" + phrase;
return data;
},
categories: [
{
listLocation: "menus",
header: "--<strong>Menus</strong>--",
},
{
listLocation: "items", //this is where I'm having problem with
header: "--<strong>Items</strong>--",
}
],
list: {
onChooseEvent: function() {
var url = $input.getSelectedItemData().url
$input.val("")
Turbolinks.visit(url)
}
}
}
$input.easyAutocomplete(options)
})
I am try to get the complete row data on click.
I tried this code from Datatables official website -
var table = $('#example').DataTable( {
data: data,
columns: [
{ data: "UserID" },
{ data: "Name" },
{ data: "emailID" },
{ data: "Role" },
{ data: "Status" }
]
} );
$('#example tbody').on( 'click', 'tr', function () {
var data = table.row(this).data();
alert( "Value = "+data[0] );
} );
But getting the Value = undefined.
Solution for this is -
Instead of -
alert( "Value = "+ data[0] );
We have to access it in this way because its an object -
alert( "Value = "+ data.UserID );
Initialize table object like this:
var table = $('#example').DataTable();
I have this piece of JS, where I have create action with Ajax:
$(document).ready(function() {
editor = new $.fn.dataTable.Editor( {
table: "#user_groups_table",
template: '#user_groups_form',
display: "details",
idSrc: "id",
ajax: {
create: {
type: 'POST',
url: '/strongbolt/user_groups',
}
},
fields: [ {
name: "name"
}, {
name: "description"
}, {
type: "checkbox",
name: "users[].id",
optionsPair: {
label: 'name',
value: 'id'
}
}, {
type: "checkbox",
name: "roles[].id",
optionsPair: {
label: 'name',
value: 'id'
}
}
]
} );
editor.on( 'preSubmit', function ( e, data, action ) {
if ( action === 'create' ) {
data.strongbolt_user_group = {
"name": data.data[0].name,
"description": data.data[0].description,
"user_ids": data.data[0].users,
"role_ids": data.data[0].roles
};
delete data.data;
}
} );
The last section which starts with editor.on( 'preSubmit', function ( e, data, action ) { basically modifies data before they are passed to server.
At the moment I get my params in terminal like this:
{
"strongbolt_user_group"=>{
"name"=>"Some test group",
"description"=>"Some test description",
"user_ids"=>{"0"=>{"id"=>"3"}, "1"=>{"id"=>"2"}, "2"=>{"id"=>"5"}},
"role_ids"=>{"0"=>{"id"=>"1"}, "1"=>{"id"=>"2"}}
}
}
however I need it to be like this:
{
"strongbolt_user_group"=>{
"name"=>"Some test group",
"description"=>"Some test description",
"user_ids"=>["3", "2", "5"],
"role_ids"=>["1", "2"]
}
}
Basically I need user_ids and role_ids to be array.
How do I modify this in my JS, please? Thank you!
You have to map the array (or array-like object) of objects to an array of their ids:
"user_ids": Array.prototype.map.call(data.data[0].users, function(o) { return o.id; }),
If you are certain that data.data[0].users is an array, then just use map without call like:
"user_ids": data.data[0].users.map(function(o) { return o.id; }),
or even shorter in ES 6's arrow functions:
"user_ids": data.data[0].users.map(o => o.id),
Note: same applies for role_ids.
I don't see any error from console window, either I don't see that my code acted. How do I investigate and make my script fired correctly? Thanks
var mylist = [
{ title: 'a' },
{ title: 'b' },
{ title: 'c' },
{ title: 'd' },
{ title: 'e' },
{ title: 'f' },
{ title: 'g' },
{ title: 'h' },
{ title: 'i' },
{ title: 'j' },
{ title: 'k' },
{ title: 'l' },
{ title: 'm' },
{ title: 'n' },
{ title: 'o' },
{ title: 'p' },
{ title: 'q' }
];
$.getJSON(mylist, function( data ) {
var items = [];
console.log(items);
$.each( data, function( key, val ) {
items.push( "<li id='" + key + "'>" + val + "</li>" );
});
$( "<ul/>", {
"class": "my-list",
html: items.join( "" )
}).appendTo( "body" );
});
You have a misunderstanding of what $.getJSON does. As you can read the in the documentation, the first argument must be a URL. $.getJSON then performs an Ajax request to the URL and parses the response as JSON.
You don't pass a URL and you don't even have JSON. All you have to do is iterate over the array:
var items = [];
$.each( mylist, function( key, val ) {
items.push( "<li id='" + key + "'>" + val + "</li>" );
});
$( "<ul/>", {
"class": "my-list",
html: items.join( "" )
}).appendTo( "body" );
DEMO
I don't know which output you want, but that should give you a start. Read the $.each documentation, and learn about how to access objects.