How to present different editor page based off of logic

I am working on a database to track packages received and packages shipped. A package is received, the contents are processed and inspected, and then the package is shipped out again. When a user is receiving a package, he will create an instance on the ‘package’ entity. The user only needs to see a subset of the attributes in ‘package’ (‘date received’, ‘receiving user’, ‘package number’). The same is true when the package is being shipped out (the user only needs to see/edit ‘date shipped’ and shipping user’ attributes).

How can I implement this functionality?

1 Like

So far I have figured out how to selectively make individual fields visible and invisible with the pistInit() function in the controller. But it seems clumsy. Surely there must be a way to have multiple edit screens for the same entity, right?

Sure. When creating a screen for an entity in Studio, it will show a dialog if the screen with the same id, descriptor or controller already exists. Just change the conflicting value for the new screen (ID at least), and you will have multiple edit screens for the same entity.

In order to use an edit screen with non-standard ID (not conforming to “entityName.edit” pattern), you have to specify the ID for the CreateAction and EditAction using their setWindowId() method (see Standard Actions over Collection - CUBA Platform. Developer’s Manual), or use openEditor() method directly in a custom action or a handler method which is set in the “invoke” attribute of a button.

2 Likes

Hello,

I am trying to do just this. Where studio do I implement setWindowId() ?

I have two different edit screens for the same entity, but I can’t seem to locate the field in studio where I set the ID of the screen I would like the second “EDIT” button to open.

https://doc.cuba-platform.com/manual-6.5/list_actions.html?_ga=2.16511990.191395458.1506339740-1270039779.1498568825

You cannot do it from Studio UI or in XML. You have to do it programmatically: inject the action into the controller and use its setWindowId() method.

1 Like

Hello, I assume I would do that in the Browse Screen controller.
Is there anywhere where I can see an example of the syntax of this being done? The documentation doesn’t show an example of setWindowId() being used. What I am trying to do is have a button that opens up a separate edit screen that only applies to a couple of fields in the entity.
Thank you in advance.

package com.company.kellygroupapp.web.listing; 
import com.haulmont.cuba.gui.components.AbstractLookup; 
public class ListingBrowse extends AbstractLookup { 
} 

Getting a build failed message currently

package com.company.kellygroupapp.web.listing; 

import com.haulmont.cuba.gui.components.AbstractLookup;

public class ListingBrowse extends AbstractLookup {


    public void onCloseListingBtnClick() {
    ListingsTableEdit.setWindowId("kellygroupapp$Listing.closeListing") 
    }
}

See here at the bottom of the file:

It’s a part of this cookbook recipe: Business Logic in Controllers - CUBA Platform. Developer’s Manual

Thank you, I think I am getting warmer.
I seem to get 1 compile error.

Error:

:app-web:compileJavaC:\Users\tmeacham\studio-projects\kellygroupapp\modules\web\src\com\company\kellygroupapp\web\listing\ListingBrowse.java:19: error: cannot find symbol
        ListingsTableEdit.setWindowId("kellygroupapp$Listing.edit.cl");
        ^
  symbol:   variable ListingsTableEdit
  location: class ListingBrowse
1 error
 FAILED

Code in controller.

package com.company.kellygroupapp.web.listing;

import com.haulmont.cuba.gui.components.AbstractLookup;
//added lines of code [start]
import com.haulmont.cuba.gui.components.actions.EditAction;
import java.util.Map;
import javax.inject.Named;
//added lines of code [end]

public class ListingBrowse extends AbstractLookup {


//added from forum example [start]
    @Named("ListingsTable.closeListing")
    private EditAction ListingTableEdit;

    @Override
    public void init(Map<String, Object> params) {
        ListingsTableEdit.setWindowId("kellygroupapp$Listing.edit.cl");
    }
    
//added from forum example &#91;end&#93;   
    
}

Is the provided example changing the screen that the default edit action opens or creating a NEW action for an edit button to open a different edit screen.

I am trying to have multiple “edit” buttons that each open a different screen of the same entity.

In the case above I am attempting to have both the original edit button that behaves as normal, and a second edit button (Close Listing) that opens a different screen with a different set of attributes exposed on the screen.

Of course, I am not sure if I am approaching this correctly.

You declare ListingTableEdit variable but reference it as ListingsTableEdit (see extra s).
Please use an IDE to write code, it will save you from silly mistakes.

1 Like

Thanks for spotting that. I was pretty sure everything matched the example, however now it now compiles but throws an error when opening the browse screen. IDE is not throwing any errors.

Error:
IllegalArgumentException: Can not set com.haulmont.cuba.gui.components.actions.EditAction field com.company.kellygroupapp.web.listing.ListingBrowse.ListingsTableCloseListing to com.haulmont.cuba.gui.xml.DeclarativeAction

Browse Controller

package com.company.kellygroupapp.web.listing;

import com.haulmont.cuba.gui.components.AbstractLookup;

//added lines of code &#91;start&#93;
//
import com.haulmont.cuba.gui.components.actions.EditAction;
import java.util.Map;
import javax.inject.Named;

//
//added lines of code &#91;end&#93;

public class ListingBrowse extends AbstractLookup {

//added from forum example &#91;start&#93;

@Named("listingsTable.closeListing")
private EditAction ListingsTableCloseListing;

    @Override
    public void init(Map<String, Object> params) {
        ListingsTableCloseListing.setWindowId("kellygroupapp$Listing.edit_close");
    }

//added from forum example &#91;end&#93;   
    


}

If I could set the window target declaratively, what I am looking to accomplish would look like this (simplified):

<actions>
  <action id="create"/>
  <action id="edit"/>
  <action id="edit_2" windowId="qms$Listing.edit2"/>
  <action id="edit_3" windowId="qms$Listing.edit3"/>
  <action id="edit_4" windowId="qms$Listing.edit4"/>
  <action id="remove"/>
</actions>

Each edit screen would have a subset of attributes available in the entire entity.

I would have one browse screen, and multiple edit screens.

Is this feasible? Does it need to be invoked by an action? IF so what is a good example of that being done?

Thanks to anyone that can assist.

package com.company.kellygroupapp.web.listing;

import com.haulmont.cuba.gui.components.AbstractLookup;
import com.haulmont.cuba.gui.components.Component;

public class ListingBrowse extends AbstractLookup {


    public void onEdit_2(Component source) {
    //something here?
    }

    public void onEdit_3(Component source) {
    //something here?
    }

    public void onEdit_4(Component source) {
    //something here?
    }
}

The problem is that there is only a generic ‘action’ XML element and the framework deduce the standard action type by the action’s id (‘edit’ for EditAction). So when you name it differently (to provide id uniqueness), the framework creates a generic action that cannot be used as an edit action.
The workaround is to create the second EditAction programmatically. For example, having the following table:

<table id="customersTable"
       width="100%">
    <actions>
        <action id="create"/>
        <action id="edit"/>
        <action id="edit_1"/>
        <action id="remove"/>
    </actions>
    <columns>
        <column id="name"/>
        <column id="email"/>
    </columns>
    <rows datasource="customersDs"/>
    <rowsCount/>
    <buttonsPanel id="buttonsPanel"
                  alwaysVisible="true">
        <button id="createBtn"
                action="customersTable.create"/>
        <button id="editBtn"
                action="customersTable.edit"/>
        <button id="editBtn_1"
                action="customersTable.edit_1"/>
        <button id="removeBtn"
                action="customersTable.remove"/>
    </buttonsPanel>
</table>

you should create the ‘edit_1’ action as follows:

public class CustomerBrowse extends AbstractLookup {

    @Inject
    private Table<Customer> customersTable;

    @Override
    public void init(Map<String, Object> params) {
        EditAction editAction1 = new EditAction(customersTable, WindowManager.OpenType.DIALOG, "edit_1");
        editAction1.setWindowId("sales$Customer.edit_1");
        editAction1.setCaption("Edit 1");
        customersTable.addAction(editAction1);
    }
}

Now the ‘edit_1’ action will open a non-standard ‘sales$Customer.edit_1’ editor screen.
See the Customers browse in the attached project.

sales.zip (118.2K)

1 Like

Everything that works in gui module should work in web (but not vice-versa). What error do you get?

1 Like

Thanks a million. That works perfectly.

One question. This only seems to work if I use the GUI module as opposed to the WEB module.
If I use the WEB module clicking the “edit 1” button returns an error.
Is that because this is only possible with the GUI module, or would there be some different code required to accomplish this with the WEB module?

The only difference seems to be which package I call.

Thanks again, I was spinning my wheels on how to achieve this.

package com.company.kellygroupapp.gui.listing;

import com.company.kellygroupapp.entity.Listing;
import com.haulmont.cuba.gui.components.AbstractLookup;
//added imports
import com.haulmont.cuba.gui.WindowManager;
import com.haulmont.cuba.gui.components.Table;
import com.haulmont.cuba.gui.components.actions.EditAction;

import javax.inject.Inject;
import java.util.Map;
//end added imports

public class ListingBrowse extends AbstractLookup {
 //code from forum
 @Inject
 private Table < Listing > listingsTable;

 @Override
 public void init(Map < String, Object > params) {
   EditAction editAction1 = new EditAction(listingsTable, WindowManager.OpenType.DIALOG, "edit_1");
   editAction1.setWindowId("kellygroupapp$Listing.edit_1");
   editAction1.setCaption("Edit 1");
   listingsTable.addAction(editAction1);
  }
  //end code from forum


}

I was unable to reproduce the error when I regenerated the screens. Thanks again!