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
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).

CSS and OSS are similar

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".

Basic syntax

Nesting

These are equivalent:

Nested
Inlined
Mix
Nested
class=User {
field=firstName {
editing=true {
visible:true;
}
}
Inlined
class=User field=firstName editing { visible:true; }
Mix
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=true

Values

Properties 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

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.

Declaration

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.

Advanced syntax

Traits

These are equivalent

As Property
As # assignment
As Property
field=firstName {
trait:required;
}
As # assignment
field=firstName#required {}

Field rank

To apply layout rules to position field in the page. These are equivalent

As Property
As Predecessor operator
As Property
field=firstName {
after:zLeft;
trait:required;
}
field=lastName {
after:firstName;
trait:required;
}
field=password {
after:lastName;
trait:required,secret;
}
As Predecessor operator
zLeft => firstName#required => lastName#required => password#required,secret

Expressions

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.