怎么给自定义的Action增加XML里的属性?


#1

我自己扩展了系统的标准CreateAction,我需要在XML里面通过设置一个属性来传值,类似下面:
<action id=“new” type=“new” foreignContainer=“xxx”/>
请问我在Action里面怎么才能取到这个foreignContainer呢?


#2

这块目前应该是不可以。XSD中只定义了标准的属性,像id,icon,shortcut,caption等,并且源码里在创建action后也只初始化这些标准属性。
理想的方式大概是可以像SpringBean一样,能支持嵌套的 Property XML元素。

同时我也发贴咨询了开发团队来确认这个问题。见:


#3

不是很理解你的case,这个 foreignContainer 怎么传值呢?xml里面只能 hard code吧,如果这样的话,可以用 id 来区分。

<action id="xxx"/>
<action id="yyy"/>

#4

就是一个字符串,我在Action里面新增了一个属性,id有id的业务用途啊,不能都通过ID来传值吧
我看了下源代码,如果能在加载Action的时候,给一个事件就能自己去处理这个逻辑了。或者系统默认把非标准的属性反射到对应的类属性上就更好了。


#5

比如我现在想做一个公用的上移、下移的Action,我需要知道排序的字段名称是什么,这个用户在使用Action的时候,通过在XML硬编码指定属性sortField=“xxx”,这样就可以使用了。有可能还会增加其他的属性来满足业务需求,不能都通过ID来传这个值吧,不知道有没有什么办法来解决这个传值问题。否则没法写通用的Action了。


#6

有没有什么办法来解决呢?


#7

如果是通用的特定功能,有个方法,不过复杂一些,可以使用fragment,其实就是界面组件化的一种实现。在 Studio 里面新建界面时,选最下面那个 fragment。然后做一个button的 fragment,
xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<fragment xmlns="http://schemas.haulmont.com/cuba/screen/fragment.xsd">
    <data>
        <collection id="customersDc" class="com.company.forum.entity.Customer" view="_local" provided="true"/>
    </data>
    <actions>
        <action id="sort" caption="sort" invoke="onSortClick"/>
    </actions>
    <layout>
        <button id="button" action="sort"/>
    </layout>
</fragment>

java: 这里添加了一个属性,用来设置排序字段的名称,并添加setter。

@UiController("forum_SortTable")
@UiDescriptor("sort-table.xml")
public class SortTable extends ScreenFragment {

    private static final Logger log = LoggerFactory.getLogger(SortTable.class);

    @Inject
    private CollectionContainer<Customer> customersDc;

    private String sortableField;

    public void setSortableField(String sortableField) {
        this.sortableField = sortableField;
    }

    public void onSortClick() {
        log.info(this.sortableField);
    }

}

在 CustomerBrowse 中的button panel加入这个 fragment:

            <buttonsPanel id="buttonsPanel"
                          alwaysVisible="true">
                <button id="createBtn" action="customersTable.create"/>
                <button id="editBtn" action="customersTable.edit"/>
                <button id="removeBtn" action="customersTable.remove"/>
                <fragment screen="forum_SortTable"/>
            </buttonsPanel>

在 Java 文件中使用:

    @Inject
    private SortTable forum_SortTable;

    @Subscribe
    private void onInit(InitEvent event) {
        forum_SortTable.setSortableField("testString");
    }

界面是这个效果:

这里有个两个问题,一个是需要在fragment嵌入的父界面用java代码设置参数,目前fragment的xml也不支持自定义参数。第二个问题是,fragment使用父界面的数据容器操作父界面数据时,需要指定数据容器的类名。所以如果要实现通用的排序,需要额外做一个persistence的排序类,然后跟具体类关联。在fragment里面注入容器的时候可以用排序类代替具体类,通过类关系图做排序和存储。


#8

用代码的话,直接在代码里面给Action设置属性就行了,就是想通过XML设置不需要写代码。是不是考虑在新版本里增加以下XML上非标准属性自动反射一下


#10

或者有没有办法让我可以重写Table的默认Loader


#11

找到一个临时方法,通过LayoutLoaderConfig的registerLoader方法,把系统默认Table的Loader换成自己的Loader,然后override方法loadStandardActionProperties,把element上非标准的属性直接反射到对应的Action属性上。


还是建议在新版本在底层AbstractComponentLoader里就实现这个默认逻辑!!


#12

如果有时间的话,可以写一篇How-to,我们也能在其它CUBA中文频道发布:grinning: