0

I have a grid provided by the struts2-jquery-grid-3.7.0 plugin as follows.

<s:url id="remoteurl" action="ProductGrid" namespace="/admin_side"/>
<s:url id="editurl" action="ProductCRUD"/>

<sjg:grid
    id="gridmultitable"
    caption="Product"
    dataType="json"
    href="%{remoteurl}"
    pager="true"
    navigator="true"
    navigatorSearchOptions="{sopt:['eq','ne','lt','gt']}"
    navigatorEdit="false"
    navigatorView="false"
    navigatorAddOptions="{height:280, width:500, reloadAfterSubmit:true}"
    navigatorEditOptions="{height:280, width:500, reloadAfterSubmit:false}"
    navigatorViewOptions="{height:280, width:500}"
    navigatorDelete="true"
    navigatorDeleteOptions="{height:280, width:500,reloadAfterSubmit:true}"
    gridModel="gridModel"
    rowList="5,10,15"
    rowNum="5"
    rownumbers="true"
    editurl="%{editurl}"
    editinline="true"
    multiselect="true"
    onSelectRowTopics="rowselect"
    onEditInlineSuccessTopics="oneditsuccess"
    viewrecords="true"
    shrinkToFit="false"
    width="1045"
    >

    <sjg:gridColumn name="prodId" index="prodId" title="Id" key="true" frozen="true" width="200" formatter="integer" editable="false" dataType="Long" sortable="true" search="true" sorttype="integer" searchoptions="{sopt:['eq','ne','lt','gt']}"/>
    <sjg:gridColumn name="prodName" index="prodName" title="Product Name" width="200" editable="true" sortable="true" search="true" sorttype="text"/>
    <sjg:gridColumn name="prodCode" index="prodCode" title="Product Code" width="200" sortable="true" search="true" editable="true" sorttype="text"/>

    <!--Start nested properties-->

    <sjg:gridColumn name="subCategory.category.catName" index="subCategory.category.catName" title="Category" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="subCategory.subCatName" index="subCategory.subCatName" title="SubCategory" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="brand.brandName" index="brand.brandName" title="Brand" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="fabric.fabricName" index="fabric.fabricName" title="Fabric" width="200" sortable="true" search="true" editable="true" sorttype="text"/>

    <!--End nested properties-->

    <sjg:gridColumn name="marketPrice" index="marketPrice" title="Market Price" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="salePrice" index="salePrice" title="Sale Price" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="featured" index="featured" title="Featured" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="expressDelivery" index="expressDelivery" title="Express Delivery" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="weight" index="weight" title="Weight" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="quantity" index="quantity" title="Quantity" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="visible" index="visible" title="Visible" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="latest" index="latest" title="Latest" width="200" sortable="true" search="true" editable="true" sorttype="text"/>
    <sjg:gridColumn name="prodDesc" index="prodDesc" title="Description" width="200" sortable="true" search="true" editable="true" sorttype="text"/>

</sjg:grid>

As can be seen, there are some nested properties in a few columns. They are not listed (displayed) in the given grid. The associated columns are simply left blank. The rest of the fields are displayed as usual.

I have also tried enclosing them within %{...} but to no avail.

How to display such nested properties in a grid? Is there any special treatment for them?

It was verified that these nested properties were fetched from the database and the model was initialized correctly.


Edit:

The action class:

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="json-default")
@InterceptorRefs({@InterceptorRef(value="store", params={"operationMode", "AUTOMATIC"})})
public final class ProductAction extends ActionSupport implements Serializable, ModelDriven<Product>
{
    @Autowired
    private final transient ProductService productService=null;
    private static final long serialVersionUID = 1L;

    private Product entity=new Product();
    private List<Product>gridModel=new ArrayList<Product>();

    private String id;
    // Get how many rows we want to have into the grid - rowNum attribute in the grid
    private Integer rows=5;
    // Get the requested page. By default grid sets this to 1.
    private Long page=1L;
    // sorting order - asc or desc
    private String sord;
    // get index row - i.e. user click to sord.
    private String sidx;
    // Search Field
    private String searchField;
    // The Search String
    private String searchString;
    // The Search Operation ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc']
    private String searchOper;
    // Your Total Pages
    private Long total;
    // All Records
    private Long records;
    private String oper;

    @Override
    public Product getModel() {
        return entity;
    }

    @Action(value = "ProductCRUD",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Product.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Product.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "defaultStack", params = {"validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
    public String edit() throws Exception {

        if(oper.equalsIgnoreCase("add")) {
            // Add a row.
        }
        else if(oper.equalsIgnoreCase("edit")) {
            // Update a row.
        }
        else if(oper.equalsIgnoreCase("del")) {
            // Delete a row.
        }
        return ActionSupport.SUCCESS;
    }

    @Action(value = "ProductGrid",
    results = {
        @Result(name = ActionSupport.SUCCESS, type = "json", params = {"includeProperties", "gridModel\\[\\d+\\]\\.prodId, gridModel\\[\\d+\\]\\.prodName, gridModel\\[\\d+\\]\\.prodCode, gridModel\\[\\d+\\]\\.prodDesc, gridModel\\[\\d+\\]\\.marketPrice, gridModel\\[\\d+\\]\\.salePrice, gridModel\\[\\d+\\]\\.featured, gridModel\\[\\d+\\]\\.expressDelivery, gridModel\\[\\d+\\]\\.weight, gridModel\\[\\d+\\]\\.occassion, gridModel\\[\\d+\\]\\.quantity, gridModel\\[\\d+\\]\\.visible, gridModel\\[\\d+\\]\\.latest, gridModel\\[\\d+\\]\\.subCategory, gridModel\\[\\d+\\]\\.fabric, gridModel\\[\\d+\\]\\.brand, gridModel\\[\\d+\\]\\.subCategory\\[\\d+\\]\\.category, total, records, rows, page, sord, sidx, searchField, searchString, searchOper", "excludeNullProperties", "true"})},
    interceptorRefs = {
        @InterceptorRef("params")})
    public String executeAction() {
        records=productService.rowCount().longValue();
        total=new BigDecimal(records).divide(new BigDecimal(rows), 0, BigDecimal.ROUND_CEILING).longValue();

        gridModel=productService.getList((int)(page-1)*rows, rows, new HashMap<String, String>(){{put(sidx, sord);}}, null);
        return SUCCESS;
    }

    public String getJSON() {
        return executeAction();
    }

    public List<Product> getGridModel() {
        return gridModel;
    }

    public void setGridModel(List<Product> gridModel) {
        this.gridModel = gridModel;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Integer getRows() {
        return rows;
    }

    public void setRows(Integer rows) {
        this.rows = rows;
    }

    public Long getPage() {
        return page;
    }

    public void setPage(Long page) {
        this.page = page;
    }

    public String getSord() {
        return sord;
    }

    public void setSord(String sord) {
        this.sord = sord;
    }

    public String getSidx() {
        return sidx;
    }

    public void setSidx(String sidx) {
        this.sidx = sidx;
    }

    public String getSearchField() {
        return searchField;
    }

    public void setSearchField(String searchField) {
        this.searchField = searchField;
    }

    public String getSearchString() {
        return searchString;
    }

    public void setSearchString(String searchString) {
        this.searchString = searchString;
    }

    public String getSearchOper() {
        return searchOper;
    }

    public void setSearchOper(String searchOper) {
        this.searchOper = searchOper;
    }

    public Long getTotal() {
        return total;
    }

    public void setTotal(Long total) {
        this.total = total;
    }

    public Long getRecords() {
        return records;
    }

    public void setRecords(Long records) {
        this.records = records;
    }

    public String getOper() {
        return oper;
    }

    public void setOper(String oper) {
        this.oper = oper;
    }

    @Action(value = "Product",
        results = {
            @Result(name=ActionSupport.SUCCESS, location="Product.jsp"),
            @Result(name = ActionSupport.INPUT, location = "Product.jsp")},
        interceptorRefs={
            @InterceptorRef(value = "defaultStack", params = {"validation.validateAnnotatedMethodOnly", "true", "validation.excludeMethods", "load"})})
    public String load() throws Exception {
        // This method is only needed to return an initial view on page load. Nothing to see here. Leave it empty.
        return ActionSupport.SUCCESS;
    }
}

In response, those all nested properties are empty. The JSON response for a single row is as follows.

{
  "gridModel": [
    {
      "brand": {

      },
      "expressDelivery": false,
      "fabric": {

      },
      "featured": true,
      "latest": false,
      "marketPrice": 12.00,
      "occassion": "222",
      "prodCode": "aaa",
      "prodDesc": "xxx",
      "prodId": 5,
      "prodName": "ddd",
      "quantity": 1,
      "salePrice": 12.00,
      "subCategory": {

      },
      "visible": true,
      "weight": 22.00
    }    
  ],
  "page": 1,
  "records": 5,
  "rows": 5,
  "sidx": "",
  "sord": "asc",
  "total": 1
}
15
  • What do you mean of Nested properties ? how does this subCategory.category.catName exists in your model I mean in which form i.e bean object are you want them from Value Stack ? Commented Feb 24, 2014 at 2:38
  • There is a list of products in the associated action class, List<Product> gridModel which is populated from the database, when a request to the action ProductGrid is made as shown in the grid. Each Product in the list contains a subCategory object which in turn, contains a category object. Dereferencing all of them with a dot, catName possessed by category should be accessed. Commented Feb 24, 2014 at 2:46
  • Okay .. did you try giving that direct name of the sub category object instead of giving dot and sub category ? Commented Feb 24, 2014 at 3:01
  • 1
    @Barewithme : The developer tool shows all of those properties empty like subCategory": {}. Hence the expression like subCategory.category.catName is not evaluated. Commented Feb 24, 2014 at 8:51
  • 1
    Escape the dot: gridModel\\[\\d+\\]\\.subCategory\\.category\\.catName (or gridModel\\[\\d+\\]\\.subCategory\\[\\d+\\]\\.category\\.catName if you have several subcategories for each row) Commented Feb 24, 2014 at 9:57

1 Answer 1

2

In the includePproperties param, you need to

  • specify the full path to the inner properties
  • escape the dots
  • remove the second \[\d\] notation when applied to objects that are not collections

An example:

wrong : gridModel\\[\\d+\\]\\.subCategory\\[\\d+\\]\\.category

right : gridModel\\[\\d+\\]\\.subCategory\\.category\\.catName

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.