...
1. What is custom method?
...
Custom methods service is basicly basically normal JAVA class. Only additional element is Spring '@Service' annotation.
Code Block |
|
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
import org.springframework.stereotype.Service;
@Service
public class ClassName {
// CLASS BODY
}
|
...
Access to outside service are made by Spring '@Autowired' annotation.
Code Block |
|
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
import org.springframework.beans.factory.annotation.Autowired;
...
@Autowired
private ServiceType setviceName;
|
...
2.3.1. DataDefinitionService
TODOThis service provides both information about entities model and access to database operations.
2.3.2. TranslationService
TODOService used to execute translation to users language.
2.3.3. SecurityService
TODOThis service allow you to access informations about current user.
3. custom methods
Anchor |
---|
| customValidators |
---|
| customValidators |
---|
|
...
Custom validator function has structure:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public boolean validatorMethodName(final DataDefinition dataDefinition, final Entity entity) {
// VALIDATOR METHOD BODY
}
|
...
When validation was unsuccessfull you can also add validation message to entity field using construction:
Code Block |
|
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
entity.addError(dataDefinition.getField("fieldName"), "validationMessage");
|
...
To attach created validator method to model xml file see see 'model custom validators' section. section.
If you need some sample code see Custom validator example in Examples section
...
Model hooks are methods that is executed on specific model actions (defined in xml file). Model hook method has structure:
Code Block |
|
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void modelHookMethodName(final DataDefinition dataDefinition, final Entity entity) {
// MODEL HOOK BODY
}
|
...
- modelHookMethodName - name of model hook method
- dataDefinition - dataDefinition data definition of hook event entity
- entity - hook event entity
To attach created model hook method to model xml file see see 'custom model event hooks' section. section.
If you need some sample code see Model hook example in Examples section
2.3. View hooks
View hooks are methods that is executed always where request is send to serwerserver. View hook method has structure:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void viewHookMethodName(final ViewDefinitionState state, final Locale locale) {
// VIEW HOOK BODY
}
|
Where
- viewHookMethodName - name of view hook method
- state - view statelocale - users locale
To attach created view hook method to view xml file see see 'view hooks' section section.
If you need some sample code see View hook example in Examples section.
Anchor |
---|
| viewListeners |
---|
| viewListeners |
---|
|
...
View listeners are methods that is executed when specified event is fired. View listener method has structure:
Code Block |
|
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void viewListenerMethodName(final ViewDefinitionState state, final ComponentState componentState, final String[] args) {
// VIEW LISTENER BODY
}
|
...
To attach created view listener method to view xml file see see 'view listeners' section.
If you need some sample code see View listener example in Examples section.
Anchor |
---|
| rowStyleResolvers |
---|
| rowStyleResolvers |
---|
|
2.5. Row style resolvers
(Grid's) Row style resolvers returns set of CSS clas names for given row entity. You can use them to mark specified grid rows, e.g. whith negative balance of some arbitrary values.
Resolver method is invoked for each of row entity.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public Set<String> rowStyleResolverName(final Entity rowEntity) {
// ROW STYLE RESOLVER BODY
}
|
Where
- rowStyleResolverName - arbitrary name of resolver method
- rowEntity - entity which will be shown in row
Return values (CSS classes) currently supported by Qcadoo Framework:
CSS class name | Constant | Description |
---|
redBg | RowStyle.RED_BACKGROUND | set row background to red |
boldFont | RowStyle.BOLD_FONT | set row font weight to bold |
yellowBg | RowStyle.YELLOW_BACKGROUND | set row background to yellow |
brownBg | RowStyle.BROWN_BACKGROUND | set row background to brown |
blueBg | RowStyle.BLUE_BACKGROUND | set row background to blue |
greenBg | RowStyle.GREEN_BACKGROUND | set row background to green |
Info |
---|
Prefer constants over CSS class name literals. This will help you avoid many mistakes and keep your code easier to maintain. |
Info |
---|
You can also create infinity number of your own, custom row styles - see Customizing GUI appearance section. |
To see how to bind created resolver method with view component go to 'row style resolvers' in 'Hook an Listeners' section.
If you need some sample code see Row style resolver example in Examples section.
Anchor |
---|
| criteriaModifier |
---|
| criteriaModifier |
---|
|
2.6. Criteria modifier
(Grid's) Criteria modifier allow you to modify state of the SearchCriteriaBuilder used by view component to fetch row entities.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void criteriaModifierName(final SearchCriteriaBuilder searchCriteriaBuilder) {
// CRITERIA MODIFIER BODY
}
|
Where
- criteriaModifierName - arbitrary name of modifier method
- searchCriteriaBuilder - criteria builder used by component
There is also second version of criteria modifier method that you can define:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void criteriaModifierName(final SearchCriteriaBuilder searchCriteriaBuilder, final FilterValueHolder filterValueHolder ) {
// CRITERIA MODIFIER BODY
} |
Where
- criteriaModifierName - arbitrary name of modifier method
- searchCriteriaBuilder - criteria builder used by component
- filterValueHolder - criteria value passed from before render hook.
To set FilterValueHolder you have to get it from LookupComponent in before render hook, modify it and set it again
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void beforeRenderHook(final ViewDefinitionState viewDefinitionState) {
LookupComponent lookup= (LookupComponent)
viewDefinitionState.getComponentByReference("lookupReference");
FilterValueHolder holder = lookup.getFilterValue();
holder.put("key", "value");
lookup.setFilterValue(holder);
} |
To see how to bind modifier method with view component go to 'criteria modifiers' in 'Hook an Listeners' section.
If you need some sample code see Criteria modifier example in Examples section.
3. Examples
Anchor |
---|
| customValidatorExample |
---|
| customValidatorExample |
---|
|
3.1 Custom validator example
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public boolean checkIfOrderHasTechnology(final DataDefinition dataDefinition, final Entity entity) {
Entity order = entity.getBelongsToField("order");
if (order == null) {
return true;
}
if (order.getField("technology") == null) {
entity.addError(dataDefinition.getField("order"), "products.validate.global.error.orderMustHaveTechnology");
return false;
} else {
return true;
}
} |
Anchor |
---|
| modelHookExample |
---|
| modelHookExample |
---|
|
3.2 Model hook example:
(this particular example is used within the <onSave> tag:
Code Block |
---|
public void fillOrderDatesAndWorkers(final DataDefinition dataDefinition, final Entity entity) {
if (("02inProgress".equals(entity.getField("state")) || "03done".equals(entity.getField("state")))
&& entity.getField("effectiveDateFrom") == null) {
entity.setField("effectiveDateFrom", new Date());
entity.setField("startWorker", securityService.getCurrentUserName());
}
if ("03done".equals(entity.getField("state")) && entity.getField("effectiveDateTo") == null) {
entity.setField("effectiveDateTo", new Date());
entity.setField("endWorker", securityService.getCurrentUserName());
}
} |
Anchor |
---|
| viewHookExample |
---|
| viewHookExample |
---|
|
3.3 View hook (preRender) example
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void checkIfCommentIsRequiredBasedOnResult(final ViewDefinitionState state) {
FieldComponentState comment = (FieldComponentState) state.getComponentByReference("comment");
FieldComponentState controlResult = (FieldComponentState) state.getComponentByReference("controlResult");
if (controlResult != null && controlResult.getFieldValue() != null && "03objection".equals(controlResult.getFieldValue())) {
comment.setRequired(true);
comment.requestComponentUpdateState();
} else {
comment.setRequired(false);
}
} |
Anchor |
---|
| viewListenerExample |
---|
| viewListenerExample |
---|
|
3.3 View listener hook example
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void checkAcceptedDefectsQuantity(final ViewDefinitionState viewDefinitionState, final ComponentState state,
final String[] args) {
if (!(state instanceof FieldComponentState)) {
throw new IllegalStateException("component is not input");
}
FieldComponentState acceptedDefectsQuantity = (FieldComponentState) state;
FieldComponentState comment = (FieldComponentState) viewDefinitionState.getComponentByReference("comment");
if (acceptedDefectsQuantity.getFieldValue() != null) {
if (isNumber(acceptedDefectsQuantity.getFieldValue().toString())
&& (new BigDecimal(acceptedDefectsQuantity.getFieldValue().toString())).compareTo(BigDecimal.ZERO) > 0) {
comment.setRequired(true);
} else {
comment.setRequired(false);
}
}
} |
Anchor |
---|
| rowStyleResolverExample |
---|
| rowStyleResolverExample |
---|
|
3.4 Row style resolver example
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public Set<String> productsListRowStyleResolver(final Entity product) {
final Set<String> entityStyles = Sets.newHashSet();
final String materialType = product.getStringField(ProductFields.GLOBAL_TYPE_OF_MATERIAL);
if ("04waste".equals(materialType)) {
entityStyles.add(RowStyle.RED_BACKGROUND);
}
if (StringUtils.isBlank(product.getStringField(ProductFields.EAN))) {
entityStyles.add(RowStyle.BOLD_FONT);
}
return entityStyles;
} |
Anchor |
---|
| criteriaModifierExample |
---|
| criteriaModifierExample |
---|
|
3
...
.5 Criteria modifier example
Single parameter example:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
public void filterOutNotBelongingToCurrentUser(final SearchCriteriaBuilder scb) {
scb.add(SearchRestrictions.eq("owner", securityService.getCurrentUserName()));
} |
- Context example:
Models:- Shop
- Chain
- Industry
Relations- Shop hasMany Industries
- Chain hasMany Industries
- Shop belongsTo Chain
Target: In industires lookup in shop details view show only industires that are in relation with chain of the shop.
Code Block |
---|
theme | Eclipse |
---|
language | html/xml |
---|
linenumbers | true |
---|
|
<view name="shopDetails" modelName="shop" ...>
<component type="window" name="window">
...
<component type="form" name="form" reference="form">
...
<component type="lookup" name="industry" reference="industryLookup"
field="industries" defaultVisible="false" persistent="false" hasLabel="false">
...
<criteriaModifier
class="com.qcadoo.sdt.basic.criteriaModifiers.ShopIndustryLookupCriteriaModifier"
method="restrictIndustriesToChainContext" />
</component>
...
</component>
</component>
<hooks>
<beforeRender class="com.qcadoo.sdt.basic.hooks.view.ShopDetailsBeforeRenderService"
method="setCriteriaModifierParameters"/>
</hooks>
</view>
|
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
@Service
public class ShopDetailsBeforeRenderService {
public void setCriteriaModifierParameters(final ViewDefinitionState state) {
LookupComponent industryLookup = (LookupComponent) state.getComponentByReference("industryLookup");
FormComponent form = (FormComponent) state.getComponentByReference("form");
Entity shop = form.getEntity();
if (shop.getId() != null) {
Entity chain = shop.getBelongsToField(ShopFields.CHAIN_FIELD);
FilterValueHolder holder = industryLookup.getFilterValue();
holder.put(ShopIndustryLookupCriteriaModifier.CHAIN_PARAMETER, chain.getId());
industryLookup.setFilterValue(holder);
}
}
} |
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
linenumbers | true |
---|
|
@Service
public class ShopIndustryLookupCriteriaModifier {
public static final String CHAIN_PARAMETER = "chain";
private static final String CHAIN_REQUIRED = "Chain parameter is required";
public void restrictIndustriesToChainContext(final SearchCriteriaBuilder scb, final FilterValueHolder filterValue){
if(!filterValue.has(CHAIN_PARAMETER)){
throw new IllegalArgumentException(CHAIN_REQUIRED);
}
Long chainId = filterValue.getLong(CHAIN_PARAMETER);
scb.createAlias(IndustryFields.CHAINS_FIELD, "c").add(SearchRestrictions.eq("c.id", chainId));
}
} |