webfirmframework for Java Experts
MLTP Architecture
MLTP stands for Model Logical-Template Push. The model (AKA domain object) gives the data required for logical-template. Logical Template could be a reusable custom template class containing wff java code which can generate a piece of html for the UI. Push, which is done by the framework internally itself when a template/layout is embedded by another template and we don't have to take care about the push part.
Logical-template
Logical-template is a reusable template class which can generate a specific portion of a ui with needful functionalities. The below code shows a simple example for Logical-template. The logical template may be provided model to show required data (it's not included in the below code but you can simply modify). The mere responsibility of a logical-template class is to generate a specific portion for ui with functionalities
public class ListUsersTempate extends Div implements ServerMethod {
private static final Logger LOGGER = Logger.getLogger(ListUsersTempate.class.getName());
private TBody tBody;
private Collection previousRows;
private int rowCount = 0;
private Button nextRowsButton;
private OnClick nextRowsButtonOnClick;
private OnClick commonOnClick;
private Button markGreenButton;
private Button markVioletButton;
private Button removeColoumnStyleButton;
private final Style countryColumnStyle;
public ListUsersTempate() {
super(null);
countryColumnStyle = new Style("background:yellow");
develop();
}
private void develop() {
new StyleTag(this).give(TagContent::text, """
table {
font-family: arial, sans-serif; border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
""");
new Table(this).give(table -> {
tBody = new TBody(table).give(bdy -> {
new Tr(bdy).give(tr -> {
new Th(tr).give(TagContent::text, "Company (会社)");
new Th(tr).give(TagContent::text, "Contact (接触)");
new Th(tr).give(TagContent::text, "Country (国)");
});
});
});
new Br(this);
new Br(this);
nextRowsButtonOnClick = new OnClick(this);
commonOnClick = new OnClick(this);
nextRowsButton = new Button(this, nextRowsButtonOnClick).give(btn -> {
new B(btn).give(TagContent::text, "Next");
});
markGreenButton = new Button(this, commonOnClick).give(btn -> {
new B(btn).give(TagContent::text, "Mark column green");
});
markVioletButton = new Button(this, commonOnClick).give(btn -> {
new B(btn).give(TagContent::text, "Mark column violet");
});
removeColoumnStyleButton = new Button(this, commonOnClick).give(btn -> {
new B(btn).give(TagContent::text, "Remove style from column");
});
// initially add rows
addRows();
}
private void addRows() {
Collection rows = new LinkedList();
for (int i = 0; i < 25; i++) {
Tr newTr = new Tr(null).give(tr -> {
rowCount++;
new Td(this).give(TagContent::text, "Alfreds Futterkiste " + rowCount);
new Td(this).give(TagContent::text, "Maria Anders " + rowCount);
new Td(this, countryColumnStyle).give(TagContent::text, "Germany " + rowCount);
});
rows.add(newTr);
}
if (previousRows != null) {
tBody.removeChildren(previousRows);
}
tBody.appendChildren(rows);
previousRows = rows;
}
@Override
public WffBMObject invoke(Event event) {
WffBMObject dataFromClient = event.data();
// if nextRowsButtonOnClick is equal to event.getSourceAttribute()
// then nextRowsButton will be equal to event.getSourceTag()
// because nextRowsButtonOnClick attribute is added only in
// nextRowsButton
// But, in the case of commonOnClick it's added in
// three buttons so the sourceTag must also be checked.
if (nextRowsButtonOnClick.equals(event.sourceAttribute())) {
addRows();
} else if (commonOnClick.equals(event.sourceAttribute())
&& markGreenButton.equals(event.sourceTag())) {
LOGGER.info("Mark column green");
countryColumnStyle.addCssProperties("background:green");
} else if (commonOnClick.equals(event.sourceAttribute())
&& markVioletButton.equals(event.sourceTag())) {
LOGGER.info("Mark column violet");
countryColumnStyle.addCssProperties("background:violet");
} else if (commonOnClick.equals(event.sourceAttribute())
&& removeColoumnStyleButton.equals(event.sourceTag())) {
LOGGER.info("remove style");
AbstractHtml[] ownerTags = countryColumnStyle.getOwnerTags();
for (AbstractHtml ownerTag : ownerTags) {
ownerTag.removeAttributes(countryColumnStyle.getAttributeName());
}
}
return null;
}
}
Later you can add this template class to any specific portion of ui, eg:
ListUsersTempate listUsers = new ListUsersTempate();
//suppose you have a div in the ui to add, then
div.appendChild(listUsers);