Skip to content

outernode and node documentation for developers #552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
damienflament opened this issue Apr 9, 2019 · 7 comments · Fixed by #553
Closed

outernode and node documentation for developers #552

damienflament opened this issue Apr 9, 2019 · 7 comments · Fixed by #553

Comments

@damienflament
Copy link

Hi.

I successfully implemented a table widget using the Python way (by using a root TableWidget and multiple TableEntry) and the web way (by using a single Table widget and a data ListProp).

But I'm trying to understand the way outernode and node properties can be used.

Can I use the outernode for the table DOM element and the node for the tbodyDOM element (which will contain the children) ?

Broadly speaking, the documentation says about those properties:

If you don’t understand what this is about, don’t worry; you won’t need it unless you are creating your own low-level widgets :)

OK. I think I need to understand what this is about. 😉

Thanks.

@almarklein
Copy link
Member

Haha. I will update these docs to make the use more clear.

Basically, most widgets have the same value for node and outernode. However, in some cases it helps to distinguish between the semantic "actual node" and a wrapper. E.g. the CanvasWidget does it in order to be able to use absolute positioning, and the TreeWidget for similar reasons. If your outernode already semantically represents your widget, you should probably just use that. Internally, Flexx uses the node attribute for tab-index, and binding to mouse/touch/scroll/key events.

I can see how in your case the tbody can indeed be a better fit for node.

@damienflament
Copy link
Author

I don't know if I use them correctly.

Table.py

class TableWidget(flx.Widget):

    def _create_dom(self):
        node = flx.create_element('tbody')
        outernode = flx.create_element('table', {}, [node])

        return [outernode, node]


class TableEntry(flx.Widget):

    def _create_dom(self):
        return flx.create_element('tr')


class TableEntryAttribute(flx.Widget):
    text = flx.StringProp(
        settable = True, doc = "The text shown for this attribute."
    )

    def _create_dom(self):
        return flx.create_element('td', {}, [self.text])

Main widget

class EstimatesView(flx.Widget):

    data = flx.ListProp(doc = "The data shown by the view.")

    def init(self):
        super().init()

        with widgets.TableWidget():
            for datum in self.data:
                with widgets.TableEntry():
                    widgets.TableEntryAttribute(text = datum.id)
                    widgets.TableEntryAttribute(text = datum.name)
                    widgets.TableEntryAttribute(text = datum.client)
                    widgets.TableEntryAttribute(text = str(datum.total))
        widgets.TableWidget()

Rendered HTML

<div class="flx-EstimatesView flx-Widget flx-current">
    <table class="flx-TableWidget flx-Widget">
        <tbody></tbody>
        <tr class="flx-TableEntry flx-Widget">
            <td class="flx-TableEntryAttribute flx-Widget">D-000255</td>
            <td class="flx-TableEntryAttribute flx-Widget">Culpa esse cupidatat id elit dolor adipisicing</td>
            <td class="flx-TableEntryAttribute flx-Widget">Aliqua ullamco</td>
            <td class="flx-TableEntryAttribute flx-Widget">2533.25</td>
        </tr>
        <!-- more <tr> -->
    </table>
</div>

Here, the point is that the TableEntry child nodes are inserted in the outernode, not the node.

Is it expected ? I expected them to be added to the node while the outernode is itself inserted in the parent of the TableWidget.

@almarklein
Copy link
Member

almarklein commented Apr 9, 2019

This is expected. The default implementation of _render_dom() adds the outernode of the childrento its own outernode. You probably want to implement_render_dom()on yourTableWidget`:

def _render_dom(self):    
    # todo: ... clear self.node's children
    for widget in self.children:
           self.node.appendChild(widget.outernode)
    return create_element("table", {},
        create_element("thead", {}, ...),
        self.node
    )

Actually, I think it may be easier to not use a different node and do:

class TableWidget(flx.Widget):

    def _create_dom(self):
        return flx.create_element('table')
    def _render_dom(self):        
        return create_element("table", {},
            create_element("thead", {}, ...),
            create_element("tbody", {}, [widget.outernode for widget in self.children])
        )

(Flexx re-uses DOM elements if the virtual node matches the existing one.)

@almarklein
Copy link
Member

Also note that Flexx will soon have a GridLayout (#553)

@damienflament
Copy link
Author

damienflament commented Apr 9, 2019

Also note that Flexx will soon have a GridLayout (#553)

Good. But here, I'm using a <table> to display data and allow sorting/filtering them by attributes.
I consider a GridLayout more relevant for displaying data as "cards" in a grid.

About that, I think implementing that layout using a <table> is not semantically correct. I would rather have used the CSS display property with its values table-row, table-column, table-cell, etc.

@damienflament
Copy link
Author

Thanks for your help.

@almarklein
Copy link
Member

Indeed, in that case a table makes more sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants