Populate a "new row" form as is done with an "edit row" form
Populate a "new row" form as is done with an "edit row" form
I'd like to implement a "copy row" hyperlink, next to the existing "edit" and "delete" hyperlink.
My users want to make one or two small changes to the original data before copying. I'm using "editor.create()" because a new row is being created (actually many new rows in different tables, but that's abstracted server-side).
How can I pre-populate the editor.create form with the clicked row's data, as is done when I use "editor.edit()"?
I thought of trying to use editor.edit and editor.create in the same function and of sending a special hidden form field while just using editor.edit (to tell the server's REST method for HTTP PUT to use special handling), but both seem really clunky.
My users want to make one or two small changes to the original data before copying. I'm using "editor.create()" because a new row is being created (actually many new rows in different tables, but that's abstracted server-side).
How can I pre-populate the editor.create form with the clicked row's data, as is done when I use "editor.edit()"?
I thought of trying to use editor.edit and editor.create in the same function and of sending a special hidden form field while just using editor.edit (to tell the server's REST method for HTTP PUT to use special handling), but both seem really clunky.
This discussion has been closed.
Replies
Until I can write it though, the approach I'd take is to use the `onCreateInit` event when you call `create()` (either via the TableTools button or the API) and use the `set()` method to set the values you want.
So:
1. Use clicks on row they want to use as a template
2. They then click on a 'duplicate' / 'template' button (which could attach a `one( 'onCreateInit' ... )` event handler if you want to still have a plain create
3. The event handler would read the data from the table for the selected row
4. Then it would use `set()` to populate the form.
Sorry for the brevity of this answer - but does it make sense?
Allan
#4, reading the data, is really where I'm having difficulty.
If this were an edit using onInitEdit, I could use [code]this.s.editRow[/code], but it's null.
The fnGetData documentation seems to make assumptions about [code]this[/code] which aren't the case in the onInitCreate handler.
At least, [code] var data = oTable.fnGetData( this );[/code] yields the error:
"Uncaught TypeError: Cannot call method 'toLowerCase' of undefined"
Can you give me a hint as to how to get the row data to the onInitCreate handler?
Regards,
Allan
http://editor.datatables.net/release/DataTables/extras/Editor/examples/inlineControls.html
Is it possible to get the row data when not using the TableTools plugin with Editor?
[code]
// Use a record as a template
$('#example').on('click', 'a.editor_template', function (e) {
e.preventDefault();
var data = table.fnGetData( $(this).parents('tr')[0] );
editor.create( 'Template' );
// Loop over the fields in the editor instance and use the `set` method or just statically assign them
editor.set( 'myField', data.myField );
...
} );
[/code]
Allan
Many Javascript state objects are still mysterious to me, so I wouldn't have thought to look in $(this).parents, nor would I think that "this", in the context of a called function would know anything about the table contents of the row that happens to have the text of the URI that I clicked.
In any case, your example works perfectly. I don't want to manually set each and every field; Its kind of high-maintenance and my software needs to handle any table configuration without alteration.
I found that this kind of works for filling in all fields:
[code]for (var key in data)
editor.set(key, data[key]);[/code]
...But a field in the clicked row isn't necessarily in the editor form, so I added a check. Unfortunately this turns into about O(N^2), but it's unlikely there will be tons of fields in any form, so not too big a deal:
[code]
var fieldlist = editor.fields();
for (var key in data) {
if ($.inArray(key, fieldlist) >= 0)
editor.set(key, data[key]);
}[/code]
This, however, doesn't work with joined tables at all (http://editor.datatables.net/release/DataTables/extras/Editor/examples/join.html), and the `editor.set()` documentation doesn't show how to work with joined fields, so I experimentated.
My final result is a 'copy' function that auto-detects each field, including 1:1 and 1:N joined fields (each of which have to be handled differently). Appending the `[].id` to an `editor.set()` parameter seems smelly to me (Is there a better way to do this?), but it works. Hopefully this helps another DT user or helps start the tutorial:
[code]
//
// "Copy" is clicked
//
$(jqDomTableID).on('click', 'a.editor_copy', function(e) {
e.preventDefault();
editor.create('You must change at least one field in order to copy this row.',
{
"label": "Create new row with this data",
"fn": function () { this.submit(); }
});
var fieldlist = editor.fields();
var data = dataTableObject.fnGetData($(this).parents('tr')[0]);
// Can't use Object.keys() because IE8 doesn't support it :(
for (var key in data) {
// Ensure this field from the clicked row is part of the Editor form.
// This does not work with joined tables fields, which are handled later.
if ($.inArray(key, fieldlist) >= 0) {
editor.set(key, data[key]);
}
// 1:1 fields have an 'id' property and are named "FIELDNAME.id", e.g. "manufacturer.id"
// The ".id" part is why there was no match in the field list.
else if (data[key].hasOwnProperty('id') && $.inArray(key + '.id', fieldlist) >= 0)
editor.set(key + '.id', data[key].id); // key is the field name, data[key] is the numeric id.
// 1:N fields have a numeric key for each entry and are named "FIELDNAME[].id", e.g. "brandnames[].id".
// Those entries look like, e.g. [{"id": "4","name": "TurboMax"},{"id": "27","name": "OtherBrand"}]
else if ($.inArray(key + '[].id', fieldlist) >= 0) {
var fieldIds = [];
for (var subKey in data[key]) {
if(data[key][subKey].hasOwnProperty('id'))
fieldIds.push(data[key][subKey]['id']);
}
// When setting a 1:N value in the editor, it wants only an array of id values. No names.
// Using the above example data, `editor.set` wants: [4, 27]
editor.set(key + '[].id', fieldIds);
}
}
});
[/code]
I completely agree about the setting of the fields individually being a real pain - you've got a nice solution for the problem there. Editor 1.3's new `val()` method is going to include an option for getting the data set for the whole form (i.e. just calling `val()` with no parameters will return all fields in key / value pairs).
> I wouldn't have thought to look in $(this).parents, nor would I think that "this", in the context of a called function would know anything about the table contents of the row that happens to have the text of the URI that I clicked.
It sort of does and sort of doesn't :-). `this` in a jQuery event handler callback is the element in question - so in this case the `A` tag. We can then use jQuery to find its parent `TR` row, and from there use DataTables' API to tell us the data for that row.
Regards,
Allan