TOPIC: Browse/ExplorerVirtualListView for Master/Detail?
#1123
Browse/ExplorerVirtualListView for Master/Detail? 2 Years, 6 Months ago
OK, I've got this form that I've created as an interface for my application. My application is meant to keep track of the books that I own and who, if anyone, I've loaned books to.
I have one table for the books, with schema here:
Code:


bkcatalog
    (agelvl, antique, author, awards, bkid, classification, 
        cond, cpyrt, edition, genre, illustrator, 
        isbn, lang, no_cpy, publisher, series, 
        signed, title)
    index (author,title)
    key (bkid)


I have another table for the loans, with a foreign key defined on the book table:
Code:


loans
    (bookid, lndate, lnid, lnname)
    index (bookid) in bkcatalog(bkid) cascade
    key (lnid)


In keeping with the user manual section on Master/Detail, I defined a rule for the bookid field of the loans table, which is supposed to populate every new record in loans using the bkid of the currently selected book in an ExplorerVirtualListView. Here's the rule:
Code:


Rule_bookid
function ()
{
return .bkid;
}


Using this with a second ExplorerVirtualListView embedded inside my main ExplorerVirtualListView triggers the existing rule for the bkid field, which returns the next number for bkid, not the bkid in the currently selected book record.
Using this with a Browse control fails completely and returns all manner of errors just trying to load the form.
I've gotten around this using a dialog that browses a query of the loans table for the currently selected book, but I'd much rather have the rule do what it's supposed to do. I've attached a copy of my library in a zip file, so if someone could please tell me what I'm doing wrong here, I'd greatly appreciate it.
File Attachment:
File Name: lmscodelib-6fa9152ddeb0eb73e65394ff3e049965.zip
File Size: 2516
 
 
#1131
Re:Browse/ExplorerVirtualListView for Master/Detail? 2 Years, 6 Months ago
Hi,

ExplorerVirtualListView is not recommended for use in a Master-Detail relationship. It is mostly used when the query has a large amount of data since it does not load all the records into memory. It is possible to use ExplorerListViewControl (not virtual) embedded in an AccessControl for a Master-Detail relationship. I would recommend starting with a BrowseControl embedded in an AccessControl for your master-detail relationship to start with since it is the easiest to define. Here is some example code to get you started. I have tested this in your library and it seems to work ok.

Code:


AddBooks
#(Access bkcatalog
title:  "Add Books to the Libary"
(Vert
(Form
(bkid group: 0) nl
nl
(isbn group: 0) (author group: 1) (illustrator group: 2) nl
(title group: 0) (series group: 1) (publisher group: 2) nl
(genre group: 0) nl
(classification group: 0) (agelvl group: 1) nl
(cpyrt group: 0) (edition group: 1) (no_cpy group: 2) nl
(awards group: 0) (lang group: 1) (cond group: 2) nl
(signed group: 0) nl
(antique group: 0) nl
(Heading 'Loans') nl nl)
(Browse 'loans'
columns: (lndate, lnname)
linkField: "bookid",
name: "bkid2", xstretch: 1)
)
)



You need to remove the rule on bookid since BrowseControl will automatically set this field to the proper value using the linkField specification.

Also, since you are already displaying bkid on the screen, and the Browse needs to be named with the key field, you'll need to define another rule that just returns whatever is in the bkid field. Use this as the name of the Browse as in the example above.

Code:


Rule_bkid2
function ()
{
return .bkid
}



This is necessary because two controls in the same Access can not have the same name or there will be confusion.

Hopefully this will get you started. Once you have this working you can work on substituting ExplorerListViewControl for the loans if you want. I hope you find this helpful.
 
 
Jeff Ferguson
Suneido Software
 
#1137
Re:Browse/ExplorerVirtualListView for Master/Deta 2 Years, 6 Months ago
OK, that all looks great, and it does work well. Here's the problem: A Browse control that works inside an Access control won't work inside an ExplorerListView. Is it possible to have a Browse control link to an Access in reverse? Meaning, have whatever record you select in the Browse populate its data into an Access? The Access1 control might work for that (have the Browse listen for changes in selection that would then reset the Access1's query, etc). Or is there some way to make the Browse work inside the ExplorerListView that I can't see? Sorry for asking all these odd questions, but I really want to use that ExplorerListView if I can... :unsure:
 
 
#1138
Re:Browse/ExplorerVirtualListView for Master/Deta 2 Years, 6 Months ago
I am sure it could be made to work, but it could be tricky because Browse and ExplorerListView are both quite complex. Sorry, no easy answer!

Have you looked at AccessNavControl?
 
 
andrew
 
#1140
Re:Browse/ExplorerVirtualListView for Master/Deta 2 Years, 6 Months ago
andrew wrote:
I am sure it could be made to work, but it could be tricky because Browse and ExplorerListView are both quite complex. Sorry, no easy answer!

Have you looked at AccessNavControl?

Ahhhh, now this has promise. :) Thanks for mentioning it to me. I'll have to play with it a bit, but it looks like it'll be a lot easier to set up than an ExplorerListView. Worst that will happen is I'll have to change the keys to make the navbar's list more meaningful.
 
 
#1147
Re:Browse/ExplorerVirtualListView for Master/Deta 2 Years, 6 Months ago
OK, the AccessNavControl is working out very nicely, except for two issues:
1. Here is my definition of my AccessNav, which is called AddBooks in my library...

AddBooks
#(AccessNav "bkcatalog"
title: "Add Books to the Libary"
(Vert (Form
(isbn group: 0) (author group: 1) (illustrator group: 2) nl
(title group: 0) (series group: 1) (publisher group: 2) nl
(genre group: 0) nl
(classification group: 0) (agelvl group: 1) nl
(cpyrt group: 0) (edition group: 1) (no_cpy group: 2) nl
(awards group: 0) (lang group: 1) (cond group: 2) nl
(signed group: 0) nl
(antique group: 0))
(Browse 'loans'
columns: (lndate, lnname)
linkField: "bookid",
name: "bkid", xstretch: 1
headerFields: #(bkid)
)
)
)

According to the definition of AccessNav, there's an argument I can use called "navigate", which will work to define what keys will be shown in the navigation bar. I've define bkcatalog's keys as "key (author, title, bkid)", bkid being a timestamp to ensure uniqueness. The only reason for including author and title is for "readability" for the user, so he/she can see more than just a string of apparently random numbers when he/she browses the library. So the syntax for defining something like that should be "navigate: (keys: (author,title,bkid))" in the AccessNav definition. But if I use that, I get an error saying "Invalid key(s) specified". Even though I've defined those fields as a composite key in my table.

2. The Browse shown in the above definition won't allow me to add new loans to the loans table. When I enter a loan, it won't save to the table. Once I save the record I'm working with, the loan information is lost the instant I switch to another book record.
 
 
#1148
Re:Browse/ExplorerVirtualListView for Master/Deta 2 Years, 5 Months ago
steelwing wrote:
OK, the AccessNavControl is working out very nicely, except for two issues:
1. According to the definition of AccessNav, there's an argument I can use called "navigate", which will work to define what keys will be shown in the navigation bar. I've define bkcatalog's keys as "key (author, title, bkid)", bkid being a timestamp to ensure uniqueness. The only reason for including author and title is for "readability" for the user, so he/she can see more than just a string of apparently random numbers when he/she browses the library. So the syntax for defining something like that should be "navigate: (keys: (author,title,bkid))" in the AccessNav definition. But if I use that, I get an error saying "Invalid key(s) specified". Even though I've defined those fields as a composite key in my table.

OK, no solution to this one. Apparently with a composite key only the first column gets shown.

2. The Browse shown in the above definition won't allow me to add new loans to the loans table. When I enter a loan, it won't save to the table. Once I save the record I'm working with, the loan information is lost the instant I switch to another book record.
Figured this one out. The BrowseControl has a method called On_Global_Save() that triggers a save of all dirty records in the Browse. I just call that method when I click a Save button. There's probably a better way of capturing that, like waiting for an event that says records in the browse have been changed and triggering a global save on that. But while I know how to capture events like that in Java, I have no clue how to do it in Suneido. The manual gives no description of what events particular controls can be registered to trigger, other than the basic triggers for button-clicks...