Understand your rules
In Previous chapter we created
User.oss
file which is our object stylesheet to drive our user interface. The same way you would use your .css
cascading style sheet to adjust your UI.Let's look little bit close on this file:
src/app/rules/User.oss
Defines basic object styles for Domain class User
class=User {
field=uniqueName {
label:"Id";
}
field=name {
label:"Name";
}
field=description {
trait:longtext;
}
zNone => *;
zLeft => uniqueName => name => description => created;
}
/*
Sample definition for operations edit and create
*/
class=User {
operation=(edit, create) {
zNone => *;
zLeft => name => description;
}
operation=(create) {
zNone => *;
zLeft => name => description => created;
}
}
The rule format is inspired by CSS and just like CSS it can be additive where more common rules can be overriden by more specific fules but extended to support nesting (just like
.sass
) and chaining and tweaked to deal with identified containing the .
(e.g. field path user.address.city
).
Both have
selectors
and properties.
CSS example
div#toc a {
text-decoration:underline;
}
If an
a
tag appears in a div
named toc set property text-decoration:underline
MetaUI OSS example
class=User field=firstName {
hint:"Your email";
}
If the field name
email
appears in the class named User
set property hint:"You email address
".
These are equivalent:
Nested
Inlined
Mix
class=User {
field=firstName {
editing=true {
visible:true;
}
}
class=User field=firstName editing { visible:true; }
class=User field=firstName {
editing { visible:true; }
}
As you go over different rules files (
.oss
), you could see there is no'='
inside the selector (field=firstName), but there is just field {.. } or editing { ... }.
It same as as writing field=*: This applies to all the field (common rule)
For editing (boolean value) , its the same as editing=trueProperties can work with types such as Boolean, Integer, String, List, Map and Expression.
field=password {
// boolean
editable:true;
//String literal quoted
toolTip:"This is required";
// This is how specify list of values
trait:required, secret;
choices:['Extra cheese', 'Mushroom'];
// String literal (unquoted)
component:AWPasswordField;
// Map
bindings: {
size:20;
};
// Expression
valid: ${ value.length > 5 }
}
Traits is MetaUI feature which is simlar to
mixins
in the SASS. It can help us reuse some of the functionality.For example trait
longtext
is just another rule that expands defined properties into current place.
field=description {
trait:longtext;
}
Such trait can look like this
@trait=longtext {
after:zBottom;
editable {
component:TextAreaComponent;
}
}
It moves description to the bottom of our Form Layout and if we are editing (Create or Edit operation), then we set
TextAreaComponent
as current rendering component.
Not always we render fields from our domain class sometimes in the enterprise we want to have some ad-hoc fields some calculated fields that are created in runtime such as:
class=User {
@field=fullName {
value:${object.firstName + " " + object.lastName};
}
}
Here the
@
, creates new field and sets the value that can be combination of multiple fields like in above example. The @
means create (declare). This is the reason why we used above the @
when defining new trait.These are equivalent
As Property
As # assignment
field=firstName {
trait:required;
}
field=firstName#required {}
To apply layout rules to position field in the page. These are equivalent
As Property
As Predecessor operator
field=firstName {
after:zLeft;
trait:required;
}
field=lastName {
after:firstName;
trait:required;
}
field=password {
after:lastName;
trait:required,secret;
}
zLeft => firstName#required => lastName#required => password#required,secret
Expressions are wrapped in
${…}
and use the JS syntax and are executed using eval
function.field=budget{
valid: ${value >= 0 ? true : "Budget must be non-negative" }
}
By default when working with rules you have access to two implicit properties the
object
and value.
Last modified 3yr ago