Could someone please help me with accessing database fields in the Anvil Database. So I will have a Sub Form that will have one row in it with fields matching the table fields, then I want to do something like this
for
i in (mytable)
add_component(mysubform)
then I want to map the fields to the subform fields
my table is called cover and the fields are covername, covericon, coversums and covertooltip
Are there any examples that someone can point to on the docs that just give an example I can follow?
I did look at datagrids an you are right they are very easy, but want to display the data in my own format and the datagrid seems like it may be a little restrictive. I am actually looking at that though so will see how flexible it is, in terms of styling.
For example, one of the fields is actually a tooltip so I dont want to actually display that data in a column, I want to direct the data in that field to a styled tooltip on mouseover.
In php I would create a function with sql and then call the function. I would create the layout with divs (css) and bits of php to display the data where I want, thats what Iād like to do.
Data grids give you a default way of displaying the data, but you can completely change that if you want. When you double click on a row in the data grid in the designer, it takes you to edit the form that is used for each row. You can put other sorts of components into each column if you want, or you can have your data grid be one column and structure the row template however you want.
The data grid will still handle creating all the row templates and data binding will populate them.
Yes, although with that wireframe it actually looks a bit easier than Iād been imagining. It looks like you have one data grid for the primary cover, and another data grid for the secondary cover. Inside each data grid you have three columns, one boolean, one text, and one for the sum insured. Thatās all very doable.
Hi, just checking I am on the right track with this layout. See image, so I created 2 single line summary āsub Formsā These will be used as components in Quotation.
Iāve added a boolean field to my cover table and then created 2 server queries as follows:
#gets the results where there is a bespoke entered sum insured
@anvil.server.callable
def set_entered_insured_sums():
results = app.tables.cover.search(CoverBespoke==1)
return results
#gets the results where there is not a bespoke entered sum insured
@anvil.server.callable
def set_standard_insured_sums():
results = app.tables.cover.search(CoverBespoke==0)
return results
I created a tooltip field above each row on the sub form which I thought to code as a custom role with a CSS relative position so it will sit on top of the line above when the info button is focus it will initate an event to show the tooltip and then when lost-focus it will hide it again.
I want to create an instance of those sub forms for each of the boolean results
Q1. With those queries, do I structure as ==0 or would I say is False?
Q2. If I want to bind the result to - e.g self.cancellation which is on Quotation, what do I put in data binding? Do I put self.item[āself.cancellationā]
There are more parts to this, but how is it looking so far? Please feel free to shred it if I am completely wrong. I wont be offended coversummary|690x251
The image isnāt showing for me, so I canāt commment on that. On the query, it depends on what type your CoverBespoke field is. If itās a number, then ==0 is fine. If itās a boolean, then ==False would be best (assuming that you initialize the field to False when you add the row).
That last assumption is because any field you donāt initialize has a value of None, and ==False will not match a value of None even though both are technically false in Python terms. Best to initialize boolean fields to False when you add the row.
That will certainly not work. self.item will be a row from your data tables, the only things you can use as a key are field names from that data table.
There are a variety of ways to get non-data table row values into your data bindings. It really depends on how you have everything setup. IF your data binding is not in a data grid, then you should be able to do self.cancellation, since self at that point is the form the data binding is in.
#gets the results where there is a bespoke entered sum insured
@anvil.server.callable
def get_bespoke_insured_sums():
results = app_tables.cover.search(CoverBespoke==True)
return results
#gets the results where there is not a bespoke entered sum insured
@anvil.server.callable
def get_standard_insured_sums():
results = app_tables.cover.search(CoverBespoke==False)
return results
Client Code:
#Populate the Quote Summary Page for Standard Cover Items
self.cover_std = tuple(anvil.server.call('get_standard_insured_sums'))
self.tooltip_std.text = [str['CoverToolTip'] for ct in self.cover_std]
self.coverimage_std.source = [('CoverIcon') for ci in self.cover_std]
self.sums_insured_std.text = [str['CoverAmount'] for ca in self.cover_std]
#Populate the Quote Summary Page for Standard Cover Items
self.cover_bsp = tuple(anvil.server.call('get_bespoke_insured_sums'))
self.tooltip_bsp.text = [str['CoverToolTip'] for ct in self.cover_bsp]
self.coverimage_bsp.source = [('CoverIcon') for ci in self.cover_bsp]
self.sums_insured_bsp.text = [str['CoverAmount'] for ca in self.cover_bsp]
and here is the bit of code creating the components
for i in self.cover_std:
sc = StandardCover(i + 1)
self.card_summary_std.add_component(sc)
for i in self.cover_bsp:
bc = BespokeCover(i + 1)
self.card_summary_bsp.add_component(bc)
As you can see from the deleted posts I am struggling a bit. So my apologies if you have read my replies then seen them gone. I was doing it all wrong.
I have now created a RowTemplate and then have bound the fields to the rows. I am still trying to figure out some of it. but finally feel I am moving forwards.
I now have the repeating panel partially working, but want to populate 3 respective fields
Hopefully this makes senseā¦when working with a data grid, you automatically get a repeating panel and a row template form. You then:
Populate the data gridās repeating panel.items property with a list of dictionaries (or a search iterator, which acts like a list of dictionaries). e.g.:
self.repeating_panel_cxl.items = some_result
The data grid automatically goes through that list of dictionaries and creates an instance of a row template form for each dictionary, assigning that row templateās .item property to the dictionary
Inside the row template you write code/data bindings to use self.item to populate individual fields, e.g.:
If what you are trying to use in the row template is not in the self.item dictionary, then how you approach that depends on what youāre trying to use. It might be a variable on the form that contains the data grid, it might be a value that can be calculated out of the repeating panelās list of dictionaries (e.g. a sum), etc.
There is no path to get from the Quotation form to the repeating panel row template instance. It has to go the other way, from the repeating panel row template instance back to the Quotation form.
Assuming:
You have self.totalcancellation on the Quotation form
The Quotation form includes a data grid
You want to display self.totalcancellation in each of the repeating panelās row templates
That last seems a bit suspect, since itād be the same value in each row in the data grid. But without seeing a clone link itās hard to know exactly the hierarchy of your repeating panel, row templates, and various widgets, so Iāll assume thatās what you want to do.
You need to get Quotationās self.cancellation into a place where the repeating panelās row template can get to it. Iāll describe one easy way, but it has limitations:
In Quotation code, do something like self.repeating_panel_cxl.totalcancellation = self.totalcancellation
In the repeating panel row template, use self.parent.totalcancellation to get to that value
The limitation is that in repeating panel row templates, self.parent is not set early enough to be used in the init method or in data bindings. form_show is the earliest I typically can use self.parent.
You could also use that technique to pass a reference to the entire Quotation instance, so that the repeating panel row template could access any variable on Quotation.
Another alternative, if what you are passing into the repeating panel .items property is an actual list of dictionaries, you could add the totalcancellation value to each dictionary. Then in the row template youād use self.item['totalcancellation'] to access the value. I donāt think that works if what youāre passing is a search iterator, though, since then it thinks youāre trying to set a column in the data table.
Iām sure other people have their own techniques theyāve come up with to pass info into repeating panel row templates.
so I am assuming this bit is wrong. I have tested the other side and if I do a print statement on it, it does give me the correct value. self.repeating_panel_cxl.coversums_cxl.text
Okay, given the situation where you know that your data grids only have one row, there is a very nasty hack to go from the Quotation form into the row template instance. Your repeating panel is a container of instances of row template forms. In your case thereās only the one instance in each repeating panel. You can use:
self.repeating_panel_cxl.get_components()[0]
To get that instance, and then access components on that instance, e.g.:
This only works because you only have a single row in each data grid. It also puts code that is populating row template forms outside of the row template, so later on youāll have trouble working out where thatās being set. But it should work.