These are my early thoughts on how to structure DataTable in 3.5.0. Feedback is welcome in the comments.
new Y.DataTable({...});
new Y.DataTable.Base({...});
Y.DataTable.Base = Y.Base.create('datatable', Y.Widget, [Y.DataTable.Core]);
Y.DataTable = Y.mix(
Y.Base.create('datatable', Y.DataTable.Base, []),
Y.DataTable, true);
Class extensions CAN (if non-invasive by default)
Y.Base.mix(Y.DataTable, [ Y.DataTable.Sortable ]);
new Y.DataTable({
data: [{ ... }, { ... }, ... ]
data: modelList
data: {
source: url, function, xml
type: 'json'
schema: { ... }
}
columns: (optional) [ key, key, { key: key, config: stuff, ... }, ... ]
recordType: (optional) ModelClass
headerView: (optional) ViewClass
bodyView: (optional) ViewClass
footerView: (optional) ViewClass
summary: (optional) 'string'
caption: (optional) 'string'
});
instance
.data = modelListInstance
.head = viewInstance
.body = viewInstance
.foot = viewInstance
-
Y.DataTable.Core
Everything added to Y.Widget to make DataTable.Base
-
Y.DataTable.HeaderView
-
Y.DataTable.BodyView
-
Y.DataTable.FooterView
Used by DataTable(.Base) to render the table contents.
Referenced via configuration, not composition.
-
Y.DataTable.Source
Optional class extension.
Adds support
data
config to generate ML with DataSource load. -
Y.DataTable.Scrollable
Optional class extension.
Adds support for scrolling table. May be used to create a third instantiable class.
-
Y.DataTable.ScrollingBodyView
Used in place of DataTable.BodyView to render the scrolling table. May not be necessary?
-
Y.DataTable.Sortable
Adds support for sorting headers and sortable config.
instance.render(...)
- build <table> (markup only or off DOM node?)
- instantiate header, body, footer views passing
- the DT instance
- the created table?
- the
data
ModelList?
- call each view's render()
Logic for reacting to user input is moved to the View classes
Concern: string based rendering would have viewX.render() return a string or populate a property, but it has requirements of the DT renderer
instance.load(...)
Pass through to this.data.load(...). Let the ModelList be responsible for data interaction.
- No ModelList is provided in
data
configuration AND - No
recordType
is provided in configuration
- Use the first item in the data array to build ATTRS and Y.Base.create(...)
- If data is empty, use columns?
@mosen Thanks for the feedback!
Definitely I'll make sure the two are compatible. As to the larger issue of plugins ont being aware of one another, I'm hoping the
uiChange
event (or suite of events) will help bridge the communication gap, because, you're right, they should not be aware of one another by design. I'm hoping there will be few cases where this manifests, but I'm hoping that the new structure will help isolate the conflict areas. The proof in the pudding will come when I start working on features (PR2 and 3).That's part of the reason for having the
head
,body
,foot
properties, because the APIs that appropriate for a specific row visualization can be sequestered onto the View class. If there's a reasonable, consistent way to expose the tbody or tbodies (I don't see a problem with the thead or tfoot) that will support the wide variety of row visualizations, then I'm all for it. I'm open to suggestions.I agree with @ericf that this sounds like a good idea. I worry this will conflict with the flyweight ML, though, since there wouldn't be a permanent Model instance for each row. I don't want to reinvent any wheels.
Yeah, it's high on my performance related priority list that record/Model changes will affect isolated UI changes. That's run time behavior. The hit coming from Attribute during render time is definitely an issue. Having the record data in Attributes gives us a single place to define extra behavior like setters (aka parser) and validators and getters (formatters? --seems like View functionality), but is costly for what I would suspect is the majority use case of having a simple data map like a POJO. I have some incomplete ideas on this that I'll enumerate in a separate comment or gist.
The current structure has each cell going through several functions in the render process. Actually, all cells go through a formatter, just most through the default one. I'm pretty sure we can avoid a lot of these function calls.
Yep, that's the idea. If time allows, I'd like to create a default BodyView that uses exclusively string concatenation, but provide another that supports cell Node creation. The latter is more likely to be in 3.5.0 for backward compatibility.
I don't follow. Can you give an example of when there would need to exist a value state for a cell that was neither the attribute value or the rendered cell data?
This was part of the reason to have the
bodyView
break out. One View implementation can use row templates + Y.Lang.sub(), another could use Node creation, and another could have sub-Views for things like expandable rows. I sure hope it works out!Go make a gallery module. What are we talking about? Eh, doesn't matter. Go make a gallery module!
Similar to the
bodyView
for custom implementations, make a customheadView
.