Lookup field in a table - how to grab Lookup button and set param for browse screen?

I have a situation where I need to filter the results of a lookup (browse screen) based on the value of a field on my current screen. I guess it’s similar to a cascading lookup. The unusual factor in my case is that my lookup field is actually a field in a table, so that I have many lookup fields (one per row). I can’t seem to set the parameters for the browse screen.

I have tried modifying the answer given in this link about setting parameters for a lookup, but I can’t seem to get it to work.

This is supposed to add an action to my table. Every time a row is added (AddAction), the getWindowParams() is overridden to add my criteria to the parameters.


        pinTable.addAction(new AddAction(pinTable) {
            @Override
            public Map<String, Object> getWindowParams() {
                return ParamsMap.of("company", companyLookup.getValue());
            }
        });

My browse window has the following query:


            <query>
                <![CDATA[select e from rade$Mailfile e
where e.sourceId.mlg.offer.company = :param$company 
or :param$company is null]]>
            </query>

When I step through the code and click the Lookup (…) button for the table row created, the getWindowParams() is never called. So the :param$company is null and all rade$Mailfile rows are displayed.

What is the correct way to do this?

As is often the case, I’ve managed to solve this myself with enough research in the forum. It requires the combination of a generated table column for the PickerField (this) with a custom lookup action (this).

Here’s what I ended up with. First we need a modification to the browse screen controller to expose the datasource:


public class MailfileBrowse extends AbstractLookup {

    @Inject
    private CollectionDatasource<Mailfile, String> mailfileDs;

    public CollectionDatasource<Mailfile, String> getMailfileDs() {
        return mailfileDs;
    }

Next we need to modify the init() code (in my case ready() since my screen is an AbstractWindow):


public class BatchEntry extends AbstractWindow {

    @Inject
    private ComponentsFactory componentsFactory;

    @Named("companyLookup")
    private LookupField companyLookup;   // My criteria field (looks up a "company"

    @Named("tblPins")
    private Table<Updtrans> pinTable;   // My table of "pins" - this is where we need the filtered browse

    @Override
    public void ready() {
        super.ready();
     
       // Create a new lookup action that calls the Mailfile browse screen with the parameter map set up 

        BaseAction action = new BaseAction("lookup") {
            @Override
            public String getIcon() {
                return "components/pickerfield/images/lookup-btn.png";
            }

            @Override
            public void actionPerform(Component component) {
                MailfileBrowse mailfileBrowse = (MailfileBrowse)
                        openLookup("rade$Mailfile.browse",
                        items -> { },
                        WindowManager.OpenType.THIS_TAB,
                        ParamsMap.of("company", companyLookup.getValue()));

                //  what to do when an item is selected from the browse screen (NOTE - NOT COMPLETE CODE)
                mailfileBrowse.addCloseListener(actionId -> {
                    if (Window.SELECT_ACTION_ID.equals(actionId)) {
                        Mailfile selected = mailfileBrowse.getMailfileDs().getItem();
                        // pick up the results and do something here!
                    }
                });
            }
        };

       //  override the default column field type for my "pin" column as a PickerField
      //  set the Lookup and Clear actions - no Open action.
        pinTable.addGeneratedColumn("pin", client -> {
            PickerField field = componentsFactory.createComponent(PickerField.class);
            field.setWidth("100%");
            field.removeAllActions();
            field.addAction(action);
            field.addClearAction();
            return field;
        });
    }

The XML for my table is:


                    <table id="tblPins"
                           editable="true"
                           height="400px"
                           width="200px">
                        <columns>
                            <column id="pin"
                                    editable="true"/>
                        </columns>
                        <rows datasource="updtransDs"/>
                    </table>

The XML on my Browse screen contains the following query:


            <query>
                <![CDATA[select e from rade$Mailfile e
where e.sourceId.mlg.offer.company.id = :param$company
or :param$company is null]]>
            </query>

This query reads the “company” parameter set in my custom Lookup action. If we happen to call this browse screen from somewhere else that doesn’t provide a company parameter, the query will just show all records and not filter them.

The result of all this is that, when I choose a company and do a lookup for a pin, the browse screen only shows candidate pins (mailfile records) for the chosen company. If I choose a different company, the browse works properly and chooses the correct rows.

Hopefully somebody else finds this useful. And, of course, I would be happy to hear other solutions.

Hi,

You are right, it can be done using generated columns. But, I do not recommend reusing of one instance of Action with multiple PickerFields generated by a ColumnGenerator. You can move creation of Action to a separate method and create it on the fly inside of the generator.

Thanks. I made the change you suggested. I’ve run into another problem now. Referring to my code above - tblPins is a table of updtransDs entries, displaying the pin column.


<table id="tblPins" editable="true" height="400px" width="200px">
    <columns>
        <column id="pin" editable="true"/>
    </columns>
    <rows datasource="updtransDs"></rows>
</table>

The pin column is an association to a Mailfile record, which has an Instance name defined as “pin”. I load the selected record from the browse into updtransDs, like this:


mailfileBrowse.addCloseListener(actionId -> {
    if (Window.SELECT_ACTION_ID.equals(actionId)) {
        Mailfile selected = mailfileBrowse.getMailfilesDs().getItem();
        Updtrans updtrans = updtransDs.getItem();
        updtrans.setPin(selected);
    }
}

I load other fields into updtransDs and they all display properly in a fieldgroup I created, but for some reason the pin (instance name of the Mailfile entity) does not display in the table. What have I missed? How do I get the pin to show in tblPins?

I’m afraid we will be able to say something certain only if you provide a sample project demonstrating the problem.

Thanks. I figured it out. I forgot this line:


            field.setDatasource(pinTable.getItemDatasource(client), "pin");

My generated field wasn’t connected to the datasource properly.