Git Product home page Git Product logo

cuba-component-declarative-controllers-cuba7's Introduction

license Build Status Download

CUBA Platform Component - Declarative Controllers

CUBA component that allows to write generic features for a Controller and use them in a declarative way.

Installation

  1. declarative-controllers is available in the CUBA marketplace
  2. Select a version of the add-on which is compatible with the platform version used in your project:
Platform Version Add-on Version
7.0.x 1.0.x
7.0.x 0.8.x
6.10.x 0.7.x
6.9.x 0.6.x
6.8.x 0.5.x
6.7.x 0.4.x
6.6.x 0.2.x - 0.3.x
6.5.x 0.1.x

The latest version is: Download

Add custom application component to your project:

  • Artifact group: de.balvi.cuba.declarativecontrollers
  • Artifact name: declarativecontrollers-global
  • Version: add-on version
dependencies {
  appComponent("de.balvi.cuba.declarativecontrollers:declarativecontrollers-global:*addon-version*")
}

Motivation & Example usage: Comments feature

So what does that mean? Here's an example balvi/cuba-example-declarative-comments:

Let's say you want to add a generic "comments-feature" on entities (in our case you can comment on "Customer" as well as "Product") and you already got everything setup on the entity layer.

Now, as you want to present a default screen for comments on every browser that shows Customers or Products. How do you not duplicate the UI logic, where you add a section on the side of the browser to show the comments on a selected item?

The default answer to this would be to create a Superclass called CommentsBrowser which extends AbstractLookup. In this controller in the ready method you would probably hook into the ready callback and do your stuff.

Now you set CustomerBrowse extends CommentsBrowser and ProductBrowse extends CommentsBrowser and you are ready to go - no code shared, so what is the problem?

Inheritance works exactly once

The problem occurs when you want to implement another feature. Let's imagine, we want to have another generic feature like that it is possible to assign one or more Documents to entities. When we try to do it as above, we have the problem that ProductBrowse already extends CommentsBrowse.

How do we resolve this? Creating another subclass CommentsBrowserWithDocuments? Would work, but what if i only want the Documents feature? This would require two classes: DocumentsBrowser for the case where we want only the documents feature and the CommentsBrowserWithDocuments class for the case of both features.

Delegation to the rescue

As this does not scale at all (having five distinct features would end up in 2^5 = 32 classes), we need to do Delegation - and this is where this app-component comes into play.

Declarative definition of features through Annotations

This application component brings not only a way of dealing with the inheritance problem. It also makes it possible to, instead of programmatically define that certain features should be used, activate these generic features in a declarative way through the Usage of Annotations.

Here is how the ProductBrowse looks with the declarative definition of the Comments feature:

@Commentable(listComponent = "productsTable")
@HasDocuments(listComponent = "productsTable", createDocument = true)
public class ProductBrowse extends AnnotatableAbstractLookup {

}

The CustomerBrowse looks like this:

@Commentable(listComponent = "productsTable")
public class CustomerBrowse extends AnnotatableAbstractLookup {

}

You just pick and choose your features and the implementation gets injected into your controllers. The only requirement is that your Controller extends from AnnotatableAbstractLookup instead of AbstractLookup directly (or AnnotatableStandardEditor for editor controllers). But this is the only superclass you need to extend from. Not for every feature another superclass.

Defining Annotations

Generally, there is another example repository, which shows the usage of this application component: balvi/cuba-example-declarative-comments with the exact example of the @Commentable.

The application component allows two kinds of Annotations. A class-based Annotation and a field-based Annotation.

Class-based Annotation: @Commentable

To create custom feature like @Commentable you have to do the following:

  1. Create a Annotation in your web module like this:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Commentable {
    String listComponent() default "";
    String buttonId() default "commentBtn";
    String buttonsPanel() default "buttonsPanel";
}

When you want to parameterise your Annotation, you can define these settings as well as default values within the Annotation.

  1. Create a spring bean (in the web module) that implements either BrowseAnnotationExecutor or EditorAnnotationExecutor for Browse screens or Editors which contains the logic that sholuld get injected into the controllers:
@Component
class CommentableBrowseAnnotationExecutor implements BrowseAnnotationExecutor<Commentable> {


    @Override
    boolean supports(Annotation annotation) {
        annotation instanceof Commentable
    }
    
    @Override
    void init(Commentable annotation, Window.Lookup browse, Map<String, Object> params) {
        // do your logic to add a button to the browse screen...
    }


    @Override
    void ready(Commentable annotation, Window.Lookup browse, Map<String, Object> params) {

    }
}

The supports method declares for which Annotation this class is responsible. Besides that it contains Hook methods for the corresponding Controllers (just like in the regular controllers).

For Browse screens these are:

  • init
  • ready

When overriding init method into your controllers, make sure to call its super method:

@Override
void init(Map<String, Object> params) {
      super.init(params)
      //your code here ...
}

For editors the hook methods are:

  • init
  • postInit

Those hook methods have the same semantics as the standard CUBA controller hook methods. For more information you can take a look at the corresponding CUBA docs for AbstractLookup and AbstractEditor.

Field-based Annotations

Field based annotations are useful if you want to enhance a particular Component on the page.

You can find the example for this in the example-project: @IconCommentedEntities

That's it.

With this you have a single place where you can put your UI logic that is accessible for different screens.

You can easily take this and create CUBA studio templates that will add your Annotations to your screens, so that you have a UI where you have a couple of checkboxes enable all of your generic features.

cuba-component-declarative-controllers-cuba7's People

Contributors

bresche avatar genthalili avatar mariodavid avatar muxa92 avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.