You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@pivot.apache.org by Dirk Möbius <dm...@scoop-gmbh.de> on 2010/12/06 17:59:10 UTC

Realizing master-detail

I'm thinking about the most elegant way to realize a master-detail  
relationship in Pivot 2.0. A common use case for my application is  
that there is a master TableView, displaying some entries of a search  
result, and a detail form below displaying detailed information about  
the selected item of the TableView. That is, something like the  
StockTracker demo.

What I don't like about the StockTracker demo is the load/store  
approach triggered by a TableViewSelectionListener. I will have _lots_  
of master detail panels in my app, and having each of them implement  
TableViewSelectionListener.Adapter with the load/store functionality  
is just too much repetitive code IMHO.

So I thought about using the new dynamic bind functionality of Pivot 2.0:

<TableView bxml:id="table">
   ...
</TableView>

<TablePane bxml:id="detailView>
   ...
   <TextInput bxml:id="name" text="${table.selectedRow.name}"/>
   ...
</TablePane>

but then I realized that dynamic bind only works on bean property  
paths that emit change events (understandably). "${table.selectedRow}"  
does, but not "${table.selectedRow.name}".

I could use a script performing load:

<TableView bxml:id="table">
   ...
   <tableViewSelectionListeners>
     function selectedRangesChanged(tableView, previousSelectedRanges) {
       detailView.load(tableView.selectedRow);
     }
   </tableViewSelectionListeners>
</TableView>

But this doesn't solve Save, only Load, and I would have to repeat the  
same code on all master detail panels again.

I would like to have a push in the right direction. Is there some  
better/ more elegant way to solve this problem?

Thanks,
Dirk.



Re: Realizing master-detail

Posted by Dirk Möbius <dm...@scoop-gmbh.de>.
Greg Brown <gk...@verizon.net> wrote:
> The load case is easier, since presumably you already have the  
> detail from the master to load into the detail form. I'd suggest  
> putting your detail pane in an include, and using a custom class  
> (that probably implements Bindable and extends an existing layout  
> container such as Form) as the root element. This class can expose a  
> bean property, such as "contact" via getContact() and setContact()  
> methods. setContact() can call load():
>
> public void setContact(Contact contact) {
>     load(contact);
> }
>
> Then in your BXML, you can do:
>
> <bxml:include src="contact.bxml" contact="${table.selectedRow}"/>

That's the push in the right direction I needed! Thanks! That's it!

In fact, the custom container class could be general:

public DataForm extends Form {
   public void setData(Object data) {
     load(data);
   }
}

And in the BXML I'd have:

<my:DataForm data="${table.selectedRow}">
   ...
</my:DataForm>

> The store case is tougher, since it depends entirely on how you want  
> to persist the data. Do you want to POST it to an HTTP service?  
> Update a database table? Save it to a file? Something else?

The data will be send to a Spring service bean eventually, a method  
call such as ContactsManager.save(data).

> Since there's not really any generic way to handle this, you'll  
> probably need to write logic to handle stores - however, the store()  
> method makes this pretty easy. Your implementation of getContact()  
> could create a new Contact instance and store() the form to it; then  
> you can do whatever you need to with that object.

All my form panels have a "save" button, which will store the form  
data back to the selected table row value. I see now that this is easy  
to accomplish with the above design.

Thanks,
Dirk.




Re: Realizing master-detail

Posted by Greg Brown <gk...@verizon.net>.
The load case is easier, since presumably you already have the detail from the master to load into the detail form. I'd suggest putting your detail pane in an include, and using a custom class (that probably implements Bindable and extends an existing layout container such as Form) as the root element. This class can expose a bean property, such as "contact" via getContact() and setContact() methods. setContact() can call load():

public void setContact(Contact contact) {
    load(contact);
}

Then in your BXML, you can do:

<bxml:include src="contact.bxml" contact="${table.selectedRow}"/>

Any time the selected row changes, setContact() will be called, and the detail form will be updated.

The store case is tougher, since it depends entirely on how you want to persist the data. Do you want to POST it to an HTTP service? Update a database table? Save it to a file? Something else?

Since there's not really any generic way to handle this, you'll probably need to write logic to handle stores - however, the store() method makes this pretty easy. Your implementation of getContact() could create a new Contact instance and store() the form to it; then you can do whatever you need to with that object.

G

On Dec 6, 2010, at 11:59 AM, Dirk Möbius wrote:

> I'm thinking about the most elegant way to realize a master-detail relationship in Pivot 2.0. A common use case for my application is that there is a master TableView, displaying some entries of a search result, and a detail form below displaying detailed information about the selected item of the TableView. That is, something like the StockTracker demo.
> 
> What I don't like about the StockTracker demo is the load/store approach triggered by a TableViewSelectionListener. I will have _lots_ of master detail panels in my app, and having each of them implement TableViewSelectionListener.Adapter with the load/store functionality is just too much repetitive code IMHO.
> 
> So I thought about using the new dynamic bind functionality of Pivot 2.0:
> 
> <TableView bxml:id="table">
>  ...
> </TableView>
> 
> <TablePane bxml:id="detailView>
>  ...
>  <TextInput bxml:id="name" text="${table.selectedRow.name}"/>
>  ...
> </TablePane>
> 
> but then I realized that dynamic bind only works on bean property paths that emit change events (understandably). "${table.selectedRow}" does, but not "${table.selectedRow.name}".
> 
> I could use a script performing load:
> 
> <TableView bxml:id="table">
>  ...
>  <tableViewSelectionListeners>
>    function selectedRangesChanged(tableView, previousSelectedRanges) {
>      detailView.load(tableView.selectedRow);
>    }
>  </tableViewSelectionListeners>
> </TableView>
> 
> But this doesn't solve Save, only Load, and I would have to repeat the same code on all master detail panels again.
> 
> I would like to have a push in the right direction. Is there some better/ more elegant way to solve this problem?
> 
> Thanks,
> Dirk.
> 
>