Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
Disable elements of the user interface¶
Lino provides several methods to customize whether data is editable or not.
Disable individual fields¶
Sometimes you want to disable (make non-editable) individual fields of a form based on certain conditions. The conditions for disabling individual fields can be application specific and based e.g. on user roles or the values of certain other fields of the object being displayed.
For example, in Lino Così an invoice disables most fields when it has been registered. Here are two screenshots of a same invoice, once when the invoice’s state is “draft” and once when it is “registered”:
In Lino you define this behaviour by overriding the disabled_fields
instance method on your model.
- class lino.core.model.Model
- disabled_fields(self, ar)¶
Return a set of field names that should be disabled (i.e. not editable) for this database object.
Here is a fictive example:
class MyModel(dd.Model):
...
def disabled_fields(self, ar):
s = super(MyModel, self).disabled_fields(ar)
...
return set()
The Invoice
model used in above screenshots does something
like this:
class Invoice(dd.Model):
...
def disabled_fields(self, ar):
df = super(Invoice, self).disabled_fields(ar)
if self.state == InvoiceStates.registered:
df.add('subject')
df.add('payment_term')
...
return df
The decision which fields to disable may depend an the current user. Here is a
fictive example of a model Case
where only the author may change first
and last name:
class Case(dd.Model):
...
def disabled_fields(self, ar):
df = super(Case, self).disabled_fields(ar)
if self.author == ar.get_user():
return df
df.add('first_name')
df.add('last_name')
return df
You may want to override this method on the actor instead of per model. In that case it must be a classmethod with two arguments obj and ar:
@classmethod
def disabled_fields(cls, obj, ar):
s = super(MyActor, cls).disabled_fields(obj, ar)
...
return set()
Note that Lino calls the disabled_fields
method
only once per database row and request. The returned set is cached in
memory.
Disable actions¶
You may also disable actions simply by adding their name to the set returned
by disabled_fields
. (The method
name disabled_fields()
is actually misleading, one day we might rename it
to disabled_elements()
).
Disable editing of a whole table¶
In some data windows you may want to disable editing functionality altogether.
For example lino.modlib.changes.Changes
or
lino.modlib.checkdata.Messages
. You don’t want to modify them, nor
delete them, not create new rows in these data windows. Not even when you are a
site manager.
You do this by setting Actor.editable
to False. This will remove
editing functionality for everybody.
Disable editing of a whole table¶
In other cases you want to remove editing functionality only for certain user
types. You do this by overriding the Actor.hide_editing()
method. For
example lino_xl.lib.products.Products
says that ProductsUser can see
products, but only ProductsStaff can edit them:
class Products(dd.Table):
required_roles = dd.login_required(ProductsUser)
@classmethod
def hide_editing(cls, user_type):
if user_type is not None:
if not user_type.has_required_roles([ProductsStaff]):
return True
return super(Products, cls).hide_editing(user_type)
- class lino.core.actors.Actor
- editable¶
Whether a data window on this actor is editable.
The front end uses this information to generate optimized JS code for these actors.
When this is False, Lino won’t even call
get_view_permission()
for actions that are notreadonly
.Set this explicitly to True or False to make the whole actor editable or not. Otherwise Lino will guess what you want during startup and set it to False if the actor is a Table and has a get_data_rows method (which usually means that it is a virtual table), otherwise to True.
This attribute is not inherited to subclasses.
Actors with a modified toolbar¶
The hide_top_toolbar
attribute changes the
toolbar (1) to be at the bottom of the window instead of the top and (2) to have
only actor-specific actions, i.e. no navigation buttons, no refresh button, no
displayText area.
This attribute is used only with ExtJS front end. In React it is
ignored. For example lino.modlib.system.SiteConfigs
does this:
class SiteConfigs(dd.Table):
hide_top_toolbar = True
(TODO: rename it to something else.)