HowToCustomizeCheckboxes

From Dabo Wiki
Jump to: navigation, search

How To Customize a Check Box

If you need a column that can assume only one of two mutually exclusive values, a way to manage it in the front end is to use a dCheckbox.

Natively dCheckbox binds to a boolean (true/false) column , but sometimes is useful to have two values for the field and may be another couple of values to display to the user, and both of them sometimes cannot be boolean. An example can clarify this situation (the database is postgres 8.1);

  CREATE TABLE t_preferences (
    c_username character varying(30) NOT NULL,
    c_likes_salty_food character(1) NOT NULL DEFAULT 'N'::bpchar,
    CONSTRAINT t_preferences_pk PRIMARY KEY (c_username),
    CONSTRAINT t_preferences_ck_likes_salty_food CHECK c_likes_salty_food = 'Y'::bpchar OR c_likes_salty_food = 'N'::bpchar) 
    )
  WITHOUT OIDS;

So a user can prefer to have an extra salt (character Y) or a normal amount of salt (character N) in his food.

And in the front end we would like to have a checkbox that shows Salty if checked or Normal if unchecked.

To bind a checkbox to this column is a two step procedure:

First, you'd create a property (let's call it LikesSalt in the bizobj that would handle the conversion, and bind to that property. The bizobj class would contain the following code:

def _getLikesSalt(self):
    YorN = self.getFieldVal("c_likes_salty_food")
    l_value = (YorN == "S")
    print "getLikesSalt: YorN =", YorN , " value=", l_value
    return l_value


def _setLikesSalt(self, val):
    YorN = {True: "Y", False: "N"}[val]
    print  "setLikesSalt: YorN =", YorN 
    self.setFieldVal("c_likes_salty_food", YorN)

LikesSalt = property(_getLikesSalt, _setLikesSalt, None,
    _("Intermediate to convert the Y/N column to a boolean  (bool)"))

Second, you need to open the ClassDesigner and set the DataSource property to a reference to the bizobj, and DataField property to LikesSalt.


Questions for Ed by Luca:

1) What is the dabo way to get a reference to the bizobj from the class designer?

ed: Just type the DataSource of the bizobj you want. The framework handles resolving that.

2) If A choice is the right one, how can I force a refresh/redraw of the checkbox to show the mark visible to the user? (I mean [X]? flagged or [ ]? unflagged)

ed: I'm not sure what you mean. If the current record's value for LikesSalt is True, the calling form.update() will update any data-bound controls.

3) How can I show in the caption of the checkbox the string "Salty" or "Normal"? Should I intercept the click on the checkbox and change the caption? There is no way to say to the dCheckbox to use these strings using the class designer?

ed: You can set the initial value using the prop sheet, but there is no native function in a checkbox to change caption when the value changes. You'll have to write some code and bind it to the ValueChanged event, since the value can change programmatically (from navigation, etc.) as well as from clicking.

luca: I intercepted the onValueChanged method, and, when I click on the checkbox, the caption gets changed, but this doesn't happen if I switch to another record pressing a button that invokes a prior() or next() button. Is this a consequence of question 1?

ed: Are you calling self.Form.next() in the button? That should issue the call to the form's update() method.

4) Is there any way to force a "code generation" of the form as it's been viewed by the ClassDesigner? Inspecting this source could be very helpful to understand the inner working of the class designer/dabo runtime, and I think it could avoid many questions...

ed: It doesn't generate code that is very helpful or elegant, and it does it on the fly, so the result from run to run can change. But if you really want to see it, go to dabo/lib/DesignerXmlConverter.py, and uncomment line 73.