Open gowhari opened 10 years ago
Interesting. Though your example would actually require support for both rowspan
and colspan
. I'm not 100% sure how I'd implement this, as I'm not sure how one would generally expect dynatable to interpret the given structure.
c1 | c2 | c3 | c4 | |
---|---|---|---|---|
s1 | s2 |
Also, in the above table you have "c2", "s1", and "s2" all labeled with dinstinct data-dynatable-column
attributes, which are meant to correspond with the attributes of the JSON collection. So when dynatable is filling in the table cell under "s1", should it be looking for the c2
property or the s1
property, because that cell would be under both headings simultaneously.
Assuming we figured that out, we'd still need to consider how it'd behave differently with:
c1 | c2 | c3 | c4 |
---|---|---|---|
s1 |
And then, if we were to do that, why stop at 2 rows?
c1 | c2 | c3 | c4 | ||
---|---|---|---|---|---|
s1 | s2 | ||||
t1 | t2 |
ExtJs handle it in a completely different way.
I think a simple answer is: Dynatable don't try to figure out the structure yourself.
Developer should use thead
to define her structure of colspan
, rowspan
s. And then she should explicitly define the order of columns in json, js or html.
c1 [0] | c2 | c3 [3] | c4 [4] | |
---|---|---|---|---|
s1 [1] | s2 [2] |
c1 [0] | c2 [1] | c3 [2] | c4 [3] |
---|---|---|---|
s1 |
c1 [0] | c2 | c3 [4] | c4 [5] | ||
---|---|---|---|---|---|
s1 [1] | s2 | ||||
t1 [2] | t2 [3] |
And then she should explicitly define the order of columns in json, js or html.
Yeah we're definitely not doing that. That's one of the things I couldn't stand about e.g. datatables, which was one of the main motivations of building dynatable in the first place.
I mean it is defined already in the HTML, I don't want the user to have to redefine it in the JS.
The developer should not have to explicitly define the order of the columns. That tightly couples the presentation of the data to the structure of the data, which leads to bad maintainability. It would mean that if you wanted to add a column to your table, you'd have to update your HTML, and then also update the logic in your JavaScript or JSON structure to accommodate the new column format.
Keep in mind, I haven't really used extjs, so if my understanding is off, please correct me.
Let's take a look at an example with extjs vs dynatable. Let's say you have a small table like this in your HTML:
<table id="my-table">
<thead><tr><th>Notice Period></th><th>Email Address</th></tr></thead>
<tbody></tbody>
</table>
h3. ExtJS
Keep in mind, extjs does some things dynatable doesn't do, so I only included the relevant code to accomplish with extjs what dynatable does do.
// ...
columns:[{
text: 'Notice period',
dataIndex: 'noticePeriod',
groupable: false,
filter: {
type: 'list'
}
}, {
text: 'Email address',
dataIndex: 'email',
width: 200,
groupable: false,
renderer: function(v) {
return '<a href="mailto:' + v + '">' + v + '</a>';
}]
// ...
And now, let's say you want to switch the order of the two columns and add a third column between them. You'd first need to change the HTML so that the columns are switched and the new one is added:
<table id="my-table">
<thead><tr><th>Email Address</th><th>Name</th><th>Notice Period></th></tr></thead>
<tbody></tbody>
</table>
And then change your JS to also switch the order of the columns and add the new one:
// ...
columns:[{
text: 'Email address',
dataIndex: 'email',
width: 200,
groupable: false,
renderer: function(v) {
return '<a href="mailto:' + v + '">' + v + '</a>';
}
}, {
text: 'Name',
dataIndex: 'name',
groupable: false,
filter: {
type: 'list'
}
}, {
text: 'Notice period',
dataIndex: 'noticePeriod',
groupable: false,
filter: {
type: 'list'
}
}]
// ...
h3. Dynatable
To start off with dynatable, you'd do this:
// Don't need to specify columns since dynatable figures it out from your HTML markup.
// We'll just do the same renderer for the mailto link as with the extjs example.
$('#my-table').dynatable({
writers: {
emailAddress: function(v) {
return '<a href="mailto:' + v.email + '">' + v.email + '</a>';
}
});
Now let's try making that same change again, where we switch the order of the columns and add a third column between the two, at the second index, but with Dynatable. First, we'll change the HTML again:
<table id="my-table">
<thead><tr><th>Email Address</th><th>Name</th><th>Notice Period></th></tr></thead>
<tbody></tbody>
</table>
Now, we're done. No change in the JavaScript necessary. Our presentation is mostly decoupled from our JS logic (I say "mostly" because of that email address render function, which I'm not sure we can effectively get rid of).
h3. However...
All that being said, I'm not experienced with extjs, so it could be that you're simply asking if it's possible to define your column structure either in the HTML or the JS, but not both (is that how extjs does it)? If that's the case, then you're right, dynatable requires you to specify the column structure in the HTML by default. I wanted to go ahead and write all this out so it's clear why that is.
If you wanted to be able to have an arbitrary column structure by not specifying it at all in your HTML, and to specify how each row gets written explicitly (akin to how you manually configure each column and their order in extjs), then you can certainly do that with dynatable by redefining the default row writer function:
$('#my-table').dynatable({
writers: {
_rowWriter: function(rowIndex, record, columns) {
return '<tr><td>' + record.email + '</td><td>' + record.noticePeriod + '</td></tr>';
}
});
Of course, the above is just a function that returns an HTML string to concatenate and append to the table body, so it could be as complex as it needs to be. The columns
argument in the above would be empty since you aren't defining your column headers in the HTML, but you don't necessarily need it if your function manually builds the HTML however it wants from the object.
You would also lose the automatic column header sorting functionality with the above.
By the way, having explained all that, I think we could make a simple change to dynatable which would achieve what you want. Right now, you can configure which row dynatable uses to extract the columns to associate with the records:
$('#my-table').dynatable({
table: {
headRowSelector: 'thead tr'
}
});
And then dynatable always grabs the $(headRowSelector).children('th,td')
elements for the columns.
We could instead make it so that you can pass in the direct column selector:
$('#my-table').dynatable({
table: {
columnSelector: 'thead tr th:not([colspan])'
}
});
And your HTML would look like this:
<table id="my-table">
<thead>
<tr>
<th rowspan="2" data-dynatable-column="c1">c1</th>
<!-- Since the c2 column doesn't actually map to an attribute, we don't need the data-dynatable-column attribute //-->
<th colspan="2">c2</th>
<th rowspan="2" data-dynatable-column="c3">c3</th>
<th rowspan="2" data-dynatable-column="c4">c4</th>
</tr>
<tr>
<th data-dynatable-column="s1">s1</th>
<th data-dynatable-column="s2">s2</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Note in the above example, you don't actually need all those data-dynatable-column
attributes, if the value of the attribute matches the cell text. I left it in there, because I'm assuming it was just for example purposes and the attribute names may not match the column header text.
It's very good and quite better than specifying column orders. Even in the more complex cases user can use another selector than works.
c1 | c2 | c3 | c4 | c5 | |
---|---|---|---|---|---|
s1 | s2 | ||||
t1 | t2 |
Sweet, I think that sounds like a plan. I'll put this in the queue.
@gowhari I assume you're looking for something kind of like this http://jsfiddle.net/brandonzylstra/47j3C/3/ but where the Dynatable version has data matching the static version.
@JangoSteve how about if we could just mark some column headers to be ignored, like for example with something like data-dynatable-ignore='true'
Then those <th>
elements would be skipped.
@brandondrew You can kind of already do that. You would be able to include data-dynatable-ignore
on the headers and then call dynatable with this configuration if we had this suggestion implemented from another issue:
$('#my-example').dynatable({
table: {
columnSelector: 'thead tr th:not([data-dynatable-ignore])'
}
});
So maybe that's another point for that feature request.
Any improvement on this issue? I am getting data with ajax support of dynatable and I am suffering from this.
table.settings.columnSelector
is no longer supported in dynatable 0.3.1
.
In order to fix this, in my case, I used the following workaround: added a hidden row that contains the actual columns, and select it using table.settings.headRowSelector
:
<table id="my-table">
<thead>
<tr>
<th rowspan="2">c1</th>
<th colspan="2">c2</th>
</tr>
<tr>
<th>s1</th>
<th>s2</th>
</tr>
<!-- Will be used for a proper column rendering order -->
<tr class="actual-header-columns" style="display: none;">
<th data-dynatable-column="c1"></th>
<th data-dynatable-column="s1"></th>
<th data-dynatable-column="s2"></th>
<tr>
</thead>
<tbody>
</tbody>
</table>
$('#my-table').dynatable({
table: {
headRowSelector: 'thead tr.actual-header-columns'
}
);
Seems that
colspan
is not supported in dynatable.http://jsfiddle.net/47j3C/ http://i.imgur.com/KbEvEcw.png
The result is same with or without
data-dynatable-column