I've been instrumenting the grid component and the core classes with
Debug calls to understand how things work. I have now some answers to
my previous questions. A few new questions did get prompted; they're
in-line with my answers, below.
(The following numbers do not correspond to my original question numbers.)
(1) To update the columns in a grid, we want inferColumns() to be
called. But grid was designed to have a static set of columns; there
is a check to ensure that we have no data (no columns) before we call
inferColumns().
Calling inferColumns() directly will not work either, because that
will just keep adding new columns to the component.
Instead, we must wipe out the existing columns. Seemingly, the first
line of basegrid.init() ("this.columns = []") seems to do just this.
However, the following call te basegrid.makeCellsAndColumns()
repopulates this.columns based on the contents of header.hcontent,
which in turn is populated each time we call basegrid.inferColumns().
So the solution is to wipe that out as well, at the top of
basegrid.init():
this.columns = [];
var svl = header.hcontent.subviews;
var origLen = svl.length;
for (var i = 0; i < origLen; i++) {
svl[0].destroy();
}
this.makeCellsAndColumns();
(2) Last time, I asked: "...what are those extra parameters to _rowclass?"
I believe what I'm looking for is initialize() - its signature looks
like a match, and it also calls construct(). However, according to the
JS2 specs, constructors should be named after the class, as opposed to
'initialize':
http://developer.mozilla.org/es4/spec/chapter_9_classes.html#constructor_methods
As for what those extra parameters are, the third one is the actual
set of cells that will be placed in the row we're instantiating -
these cells are determined by the column's _getCellForColumn() method,
which in turn is controlled by the lexical children of the column (via
its defaultplacement of "content").
(3) Still not sure what the "spacing" attribute is for. There is a
blob of code in LzNode.initialize() that seems to muck with the attrs
argument, but I have no idea yet what it does/whether it's relevant at
all.
(4) I understand the need for imperative code to flexibly infer
columns, but it seems everything would be vastly simplified if the
column-set, too, could be specified declaratively. For instance, using
my previous example, something like the following (note: haven't
tested) should get us node-based columns:
maindata:/maindata/item[1]/*
I don't know XPath at all, so I'd have to look up how to get the list
of attributes, but the general idea is:
maindata:/maindata/item[1]/attributes
Yang
On 7/11/07, Yang Zhang <[EMAIL PROTECTED]> wrote:
Hi, I'm trying to understand grid and how it creates/replicates
columns/cells (and hopefully learn a ton about Laszlo). Any answers
would be greatly appreciated! I've divided up this email into two
parts.
BTW, if any Laszlo devs are listening, it seems to me that grid is one
of the most frequently asked-about components (on the list and in the
forums). It is one of the more complex components, to be sure. Perhaps
more attention can be afforded to this component, in terms of built-in
features and extensibility hooks - or at least some documentation
walking through how basegrid works and how to extend it (in
non-trivial ways).
1) Changing Columns
grid expects the set of columns to never change. According to
http://forum.openlaszlo.org/showthread.php?s=&threadid=1952, I need to
call init() after updating the dataset.
I produced a small test case showing that this is insufficient. See
the attached change-cols.lzx. The columns don't change (but the rows
do disappear). If I explicitly call inferColumns(), that causes new
columns to appear (each time inferColumns() is called), but old ones
remain.
I also get an error in Debug - once when the dataset updates, and once
just for adding an "ondata" handler to the grid:
WARNING: Redefining .rowparent.replicator from Lazy clone manager in
LzView name: rowparent to «lz.basegridrow»
2) Understanding Replication
In order to get to the bottom of the above behavior, I'm currently
trying to understand the way columns and cells are created in grids.
In basegrid.makeCellsAndColumns(), I see:
var r = new _rowclass ( content.rowparent , initArgs, cells , true );
new LzDatapath( r , { replication : "lazy" ,
xpath : this.contentdatapath ,
spacing : this.spacing } );
However, in the following, I get errors:
<canvas>
<simplelayout axis="y"/>
<dataset name="maindata" oninit="classroot.doit()" ondata="classroot.doit()">
<maindata>
<item>
<cell1>alpha</cell1>
<cell2>beta</cell2>
<cell3>gamma</cell3>
</item>
<item>
<cell1>delta</cell1>
<cell2>epsilon</cell2>
<cell3>zeta</cell3>
</item>
</maindata>
</dataset>
<script>
Debug.write("running");
var t = new LzText ( canvas, { name: "replicator" } );
new LzDatapath( t , { replication: 'lazy',
xpath: 'maindata:/maindata/item/*/text()' } );
</script>
</canvas>
The output is:
running
WARNING: Redefining #replicator from #replicator to Lazy clone manager
in This is the canvas
ERROR: setHeight cannot be called on the canvas.
Yet the replication seems to be have taken place. What are these errors about?
Also, what are those extra parameters to _rowclass (which should by
default be basegridrow)? I couldn't find any documentation on this, or
on constructors in Laszlo (aside from LzNode.construct(), which only
takes 2 args), or how the "new" keyword works.
Lastly, why is there a "spacing" attribute initialized in the LzDatapath?
Thanks a lot for any help!