Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Nested ListGrid Editing with Custom Type Error

    when i upgraded to this version SmartClient Ajax RIA system Version v12.0p_2019-02-12/PowerEdition Deployment (2019-02-12)

    the following started happening when editing ListGrid with a custom type

    Click image for larger version

Name:	NestedListGridEditing.gif
Views:	414
Size:	535.3 KB
ID:	256953

    here is a test case :

    Code:
    <html>
    <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
    <SCRIPT>window.isc_useSimpleNames = false; var isomorphicDir='../isomorphic/';</SCRIPT>
    <SCRIPT SRC="../isomorphic/system/modules/ISC_Core.js">
    </script><SCRIPT SRC="../isomorphic/system/modules/ISC_Foundation.js">
    </script><SCRIPT SRC="../isomorphic/system/modules/ISC_Containers.js">
    </script><SCRIPT SRC="../isomorphic/system/modules/ISC_Grids.js"></script>
    <SCRIPT SRC="../isomorphic/system/modules/ISC_Forms.js"></script>
    <SCRIPT SRC="../isomorphic/skins/Enterprise/load_skin.js"></script>
    <SCRIPT SRC="../isomorphic/system/modules/ISC_DataBinding.js"></script>
    </head>
    <body>
    <script>
    
    isc.ClassFactory.defineClass("GridEditorItem", "CanvasItem");
    isc.SimpleType.create({
        name: "msfUOM",
        inheritsFrom: "float",
        normalDisplayFormatter: function (value) {
            var v = isc.NumberUtil.format(value/0.092903/1000.0,",0.00");
            return v;
        },
        shortDisplayFormatter: function (value) { 
            return this.normalDisplayFormatter(value);
        }
    });
    
    countryData = [
    {
        continent:"North America",
        countryName:"United States",
        countryCode:"US",
        area:0,
        areaM:0,    
        population:298444215,
        gdp:12360.0,
        independence:new Date(1776,6,4),
        government:"federal republic",
        government_desc:2,
        capital:"Washington, DC",
        member_g8:true,
        article:"http://en.wikipedia.org/wiki/United_states"
    },
    {
        continent:"Asia",
        countryName:"China",
        countryCode:"CH",
        area:0,
        areaM:0,
        population:1313973713,
        gdp:8859.0,
        government:"Communist state",
        government_desc:0,
        capital:"Beijing",
        member_g8:false,
        article:"http://en.wikipedia.org/wiki/China"
    },
    {
        continent:"Asia",
        countryName:"Japan",
        countryCode:"JA",
        area:0,
        areaM:0,
        population:127463611,
        gdp:4018.0,
        government:"constitutional monarchy with parliamentary government",
        government_desc:1,
        capital:"Tokyo",
        member_g8:true,
        article:"http://en.wikipedia.org/wiki/Japan"
    },
    {
        continent:"Asia",
        countryName:"South Korea",
        countryCode:"KS",
        area:0,
        areaM:0,
        population:48846823,
        gdp:965.3,
        independence:new Date(1945,7,15),
        government:"republic",
        government_desc:5,
        capital:"Seoul",
        member_g8:false,
        article:"http://en.wikipedia.org/wiki/South_korea"
    },
    {
        continent:"Asia",
        countryName:"Indonesia",
        countryCode:"ID",
        area:0,
        areaM:0,
        population:245452739,
        gdp:865.6,
        independence:new Date(1945,7,17),
        government:"republic",
        government_desc:5,
        capital:"Jakarta",
        member_g8:false,
        article:"http://en.wikipedia.org/wiki/Indonesia"
    }
    
    ];
    
    isc.RestDataSource.create({
        ID: 'countryDS',
        clientOnly: true,
        testData: countryData,
        fields:[
            { name: "continent"},
            { name: "countryName"},
            { name: "area", title: ('area'), type: 'msfUOM', required: true, allowEmptyValue:false},
            { name: "areaM", title: ('areaM'), type: 'msfUOM', required: false, allowEmptyValue:false},
            { name: "population", title: ('population'), type: 'float',format:',0',required: true  },
            { name: 'gdp', title: ('gdp')},
            { name: "government",title: ('government')},
            { name: "independence",title: ('independence'),type:"date", useTextField:true,required: true},
            { name: 'capital', title: ('capital'), type: 'integer' },
            { name: 'member_g8', title: ('member_g8'), type: 'boolean'},
            { name: "article",title: ('article')}
        ]
    });
    
    
    isc.GridEditorItem.addProperties({
       height:"*", width:"*",
       rowSpan:"*", colSpan:"*",
       endRow:true, startRow:true,
    
       // this is going to be an editable data item
       shouldSaveValue:true,
    
       // Override createCanvas to create the ListGrid with the user can use to set the value.
       createCanvas : function () {
    
           var gridDS = isc.DS.get(this.gridDataSource);
    
           return isc.ListGrid.create({
                autoDraw:false,
                // fill the space the form allocates to the item
                leaveScrollbarGaps:false,
    
                // dataSource and fields to use, provided to a listGridItem as
                // listGridItem.gridDataSource and optional gridFields
                dataSource:gridDS,
                fields:this.gridFields,
                sortField:this.gridSortField,
                groupByField:this.gridGroupByField,
                sortDirection: this.gridSortDirection,
                saveByCell:this.gridSaveByCell,
                editByCell:this.gridEditByCell,
                // the record being edited is assumed to have a set of subrecords
                data:this.getValue(),
                canEdit:this.gridCanEdit,
                editEvent:this.gridEditEvent,
                saveLocally:true,
                showGridSummary: true,
                showGroupSummary: true,
                showGroupSummaryInHeader: true,
                saveLocally: true, // prevents updates to the datasource
                autoFetchData:false,
                canMultiGroup: true,
                showRecordComponents: true,
                showRecordComponentsByCell: true,
                groupStartOpen:"all",
                autoFitWidthApproach:"both", 
    
                // update form when data changes
                cellChanged : function () {
                    this.canvasItem.saveValue(this.data);
                    if (this.canvasItem.gridSortField != null) {
                        this.sort(this.canvasItem.gridSortField,this.canvasItem.gridSortDirection);
                    }
                },
                //recordDoubleClick: "addItemForm.setData(record);addItemWindow.show();",
                emptyMessage: "<br>"+"nothingSelected"+"</b>",
                createRecordComponent : this.gridRecordComponent,
                cellContextClick: this.gridCellContextClick,
                    // allow Hovers
                canHover: true,
                showHover: true,
    
                // allow hoverComponents
                showHoverComponents: true,
    
                // override the builtin getCellHoverComponent() method so we can return a component of our
                // choosing - in this case, create a DetailViewer, populate it with the entire record from
                // the server and return it for display
                getCellHoverComponent : function (record, rowNum, colNum) {
                    this.rowHoverComponent = isc.DetailViewer.create({
                        dataSource: gridDS,
                        width: 250
                    });
    
                    this.rowHoverComponent.setData(record);
    
                    return this.rowHoverComponent;
                }
           });
       },
    
       // implement showValue to update the ListGrid data
       // Note that in this case we care about the underlying data value - an array of records
       showValue : function (displayValue, dataValue) {
           if (this.canvas == null) return;
           this.canvas.setData(dataValue);
       }
    
    
    
    });
    isc.DynamicForm.create({
        ID: "testForm",
        width:900,
        height:500,
        fields: [
               { name: "items", colSpan:6, align:"center", width:"*", height:"*",
                showTitle:false,
                gridCanEdit:true,
                gridEditEvent: "click",
                editorType:"GridEditorItem",
                gridDataSource:"countryDS",
                gridSaveByCell:true,
                gridEditByCell:true,
                gridFields:[
                    { name: "countryName", canEdit:false,showGridSummary:false, showGroupSummary: false},
                    { name: "area",cellChanged: function(record, newValue, oldValue, rowNum, colNum, grid){
                        if  ( newValue > 0) 
                            record.areaM = newValue / 25.4;
                        else
                            record.areaM = 0;
                        }},
                    { name: "areaM"},
                    { name: 'removeItemBtn', title:" ",width:25}
                ],
                saveLocally: true, // prevents updates to the datasource
                autoFetchData:false,
                startRow:false ,
                endRow:false,
                //gridCellContextClick:"return widthMenu.showContextMenu()",
                gridRecordComponent:function (record, colNum) {
                    var fieldName = this.getFieldName(colNum);
                    if (fieldName == "removeItemBtn") {
                        var button = isc.IButton.create({
                            height: 18,
                            width: 25,
                            icon: "general_delete.png",
                            title: "",
                            click : function () {
                                rollstockRequestForm.getItem("items").canvas.removeData(record);
                            }
                        });
                        return button;
                    } else {
                        return null;
                    }
                }
            }
        ]
    });
    
    testForm.getItem("items").canvas.setData(countryData);
    
    
    </script>
    </body>
    </html>

    #2
    Any update on this or should i try a work around of not using the nested ListGrid canvas ?

    Comment


      #3
      ok i narrowed it down ... here is what i found if you run the following using the Enterprise skin you get the error but when u switch to Tahoe it works

      Code:
      isc.ClassFactory.defineClass("GridEditorItem", "CanvasItem");
      isc.SimpleType.create({
          name: "msfUOM",
          inheritsFrom: "float",
          normalDisplayFormatter: function (value) {
              var v = isc.NumberUtil.format(value/0.092903/1000.0,",0.00");
              return v;
          },
          shortDisplayFormatter: function (value) { 
              return this.normalDisplayFormatter(value);
          }
      });
      
      countryData = [
      {
          continent:"North America",
          countryName:"United States",
          countryCode:"US",
          area:0,
          areaM:0,    
          population:298444215,
          gdp:12360.0,
          independence:new Date(1776,6,4),
          government:"federal republic",
          government_desc:2,
          capital:"Washington, DC",
          member_g8:true,
          article:"http://en.wikipedia.org/wiki/United_states"
      },
      {
          continent:"Asia",
          countryName:"China",
          countryCode:"CH",
          area:0,
          areaM:0,
          population:1313973713,
          gdp:8859.0,
          government:"Communist state",
          government_desc:0,
          capital:"Beijing",
          member_g8:false,
          article:"http://en.wikipedia.org/wiki/China"
      },
      {
          continent:"Asia",
          countryName:"Japan",
          countryCode:"JA",
          area:0,
          areaM:0,
          population:127463611,
          gdp:4018.0,
          government:"constitutional monarchy with parliamentary government",
          government_desc:1,
          capital:"Tokyo",
          member_g8:true,
          article:"http://en.wikipedia.org/wiki/Japan"
      },
      {
          continent:"Asia",
          countryName:"South Korea",
          countryCode:"KS",
          area:0,
          areaM:0,
          population:48846823,
          gdp:965.3,
          independence:new Date(1945,7,15),
          government:"republic",
          government_desc:5,
          capital:"Seoul",
          member_g8:false,
          article:"http://en.wikipedia.org/wiki/South_korea"
      },
      {
          continent:"Asia",
          countryName:"Indonesia",
          countryCode:"ID",
          area:0,
          areaM:0,
          population:245452739,
          gdp:865.6,
          independence:new Date(1945,7,17),
          government:"republic",
          government_desc:5,
          capital:"Jakarta",
          member_g8:false,
          article:"http://en.wikipedia.org/wiki/Indonesia"
      }
      
      ];
      
      isc.RestDataSource.create({
          ID: 'countryDS',
          clientOnly: true,
          testData: countryData,
          fields:[
              { name: "continent"},
              { name: "countryName"},
              { name: "area", title: ('area'), type: 'msfUOM', required: true, allowEmptyValue:false},
              { name: "areaM", title: ('areaM'), type: 'msfUOM', required: false, allowEmptyValue:false},
              { name: "population", title: ('population'), type: 'float',format:',0',required: true  },
              { name: 'gdp', title: ('gdp')},
              { name: "government",title: ('government')},
              { name: "independence",title: ('independence'),type:"date", useTextField:true,required: true},
              { name: 'capital', title: ('capital'), type: 'integer' },
              { name: 'member_g8', title: ('member_g8'), type: 'boolean'},
              { name: "article",title: ('article')}
          ]
      });
      
      
      isc.GridEditorItem.addProperties({
         height:"*", width:"*",
         rowSpan:"*", colSpan:"*",
         endRow:true, startRow:true,
      
         // this is going to be an editable data item
         shouldSaveValue:true,
      
         // Override createCanvas to create the ListGrid with the user can use to set the value.
         createCanvas : function () {
      
             var gridDS = isc.DS.get(this.gridDataSource);
      
             return isc.ListGrid.create({
                  autoDraw:false,
                  // fill the space the form allocates to the item
                  leaveScrollbarGaps:false,
      
                  // dataSource and fields to use, provided to a listGridItem as
                  // listGridItem.gridDataSource and optional gridFields
                  dataSource:gridDS,
                  fields:this.gridFields,
                  sortField:this.gridSortField,
                  groupByField:this.gridGroupByField,
                  sortDirection: this.gridSortDirection,
                  saveByCell:this.gridSaveByCell,
                  editByCell:this.gridEditByCell,
                  // the record being edited is assumed to have a set of subrecords
                  data:this.getValue(),
                  canEdit:this.gridCanEdit,
                  editEvent:this.gridEditEvent,
                  saveLocally:true,
                  showGridSummary: true,
                  showGroupSummary: true,
                  showGroupSummaryInHeader: true,
                  saveLocally: true, // prevents updates to the datasource
                  autoFetchData:false,
                  canMultiGroup: true,
                  showRecordComponents: true,
                  showRecordComponentsByCell: true,
                  groupStartOpen:"all",
                  autoFitWidthApproach:"both", 
      
                  // update form when data changes
                  cellChanged : function () {
                      this.canvasItem.saveValue(this.data);
                      if (this.canvasItem.gridSortField != null) {
                          this.sort(this.canvasItem.gridSortField,this.canvasItem.gridSortDirection);
                      }
                  },
                  //recordDoubleClick: "addItemForm.setData(record);addItemWindow.show();",
                  emptyMessage: "<br>"+"nothingSelected"+"</b>",
                  createRecordComponent : this.gridRecordComponent,
                  cellContextClick: this.gridCellContextClick,
                      // allow Hovers
                  canHover: true,
                  showHover: true,
      
                  // allow hoverComponents
                  showHoverComponents: true,
      
                  // override the builtin getCellHoverComponent() method so we can return a component of our
                  // choosing - in this case, create a DetailViewer, populate it with the entire record from
                  // the server and return it for display
                  getCellHoverComponent : function (record, rowNum, colNum) {
                      this.rowHoverComponent = isc.DetailViewer.create({
                          dataSource: gridDS,
                          width: 250
                      });
      
                      this.rowHoverComponent.setData(record);
      
                      return this.rowHoverComponent;
                  }
             });
         },
      
         // implement showValue to update the ListGrid data
         // Note that in this case we care about the underlying data value - an array of records
         showValue : function (displayValue, dataValue) {
             if (this.canvas == null) return;
             this.canvas.setData(dataValue);
         }
      
      
      
      });
      isc.DynamicForm.create({
          ID: "testForm",
          width:900,
          height:500,
          fields: [
                 { name: "items", colSpan:6, align:"center", width:"*", height:"*",
                  showTitle:false,
                  gridCanEdit:true,
                  gridEditEvent: "click",
                  editorType:"GridEditorItem",
                  gridDataSource:"countryDS",
                  gridSaveByCell:true,
                  gridEditByCell:true,
                  gridFields:[
                      { name: "countryName", canEdit:false,showGridSummary:false, showGroupSummary: false},
                      { name: "area",cellChanged: function(record, newValue, oldValue, rowNum, colNum, grid){
                          if  ( newValue > 0) 
                              record.areaM = newValue / 25.4;
                          else
                              record.areaM = 0;
                          }},
                      { name: "areaM"},
                      { name: 'removeItemBtn', title:"RMV",width:25}
                  ],
                  saveLocally: true, // prevents updates to the datasource
                  autoFetchData:false,
                  startRow:false ,
                  endRow:false,
                  //gridCellContextClick:"return widthMenu.showContextMenu()",
                  gridRecordComponent:function (record, colNum) {
                      var fieldName = this.getFieldName(colNum);
                      if (fieldName == "removeItemBtn") {
                          var button = isc.IButton.create({
                              height: 18,
                              width: 25,
                              title: "",
                              click : function () {
                              }
                          });
                          return button;
                      } else {
                          return null;
                      }
                  }
              }
          ]
      });
      
      testForm.getItem("items").canvas.setData(countryData);

      Comment


        #4
        here is the error
        Code:
        ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1997 Uncaught TypeError: Cannot read property 'length' of null
            at _3.isc_FloatItem_handleEditorEnter [as handleEditorEnter] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1997)
            at _3.isc_FormItem_elementFocus [as elementFocus] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1396)
            at _3.isc_c_Class_invokeSuper [as invokeSuper] (ISC_Core.js?isc_version=v12.0p_2019-02-20.js:315)
            at _3.isc_c_Class_Super [as Super] (ISC_Core.js?isc_version=v12.0p_2019-02-20.js:307)
            at _3.isc_ListGrid__editFormItem_elementFocus [as elementFocus] (ISC_Grids.js?isc_version=v12.0p_2019-02-20.js:862)
            at _3.isc_DynamicForm_bubbleItemHandler [as bubbleItemHandler] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:571)
            at _3.isc_DynamicForm_elementFocus [as elementFocus] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:592)
            at _3.isc_FormItem__nativeElementFocus [as $12v] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1390)
            at _3.isc_c_Class_invokeSuper [as invokeSuper] (ISC_Core.js?isc_version=v12.0p_2019-02-20.js:315)
            at _3.isc_c_Class_Super [as Super] (ISC_Core.js?isc_version=v12.0p_2019-02-20.js:307)
            at _3.isc_TextItem__nativeElementFocus [as $12v] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1921)
            at Object.isc_c_FormItem___nativeFocusHandler [as $763] (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:713)
            at HTMLInputElement.isc_c_FormItem__nativeFocusHandler (ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:708)
        isc_FloatItem_handleEditorEnter @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1997
        isc_FormItem_elementFocus @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1396
        isc_c_Class_invokeSuper @ ISC_Core.js?isc_version=v12.0p_2019-02-20.js:315
        isc_c_Class_Super @ ISC_Core.js?isc_version=v12.0p_2019-02-20.js:307
        isc_ListGrid__editFormItem_elementFocus @ ISC_Grids.js?isc_version=v12.0p_2019-02-20.js:862
        isc_DynamicForm_bubbleItemHandler @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:571
        isc_DynamicForm_elementFocus @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:592
        isc_FormItem__nativeElementFocus @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1390
        isc_c_Class_invokeSuper @ ISC_Core.js?isc_version=v12.0p_2019-02-20.js:315
        isc_c_Class_Super @ ISC_Core.js?isc_version=v12.0p_2019-02-20.js:307
        isc_TextItem__nativeElementFocus @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:1921
        isc_c_FormItem___nativeFocusHandler @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:713
        isc_c_FormItem__nativeFocusHandler @ ISC_Forms.js?isc_version=v12.0p_2019-02-20.js:708

        Comment


          #5
          Click image for larger version

Name:	NestedListGridEditing2.gif
Views:	96
Size:	941.4 KB
ID:	256980

          Comment


            #6
            What was your old version/build, the one your upgraded *from*?

            Comment


              #7
              we upgraded from
              Version v12.0p_2018-12-18/PowerEdition Deployment (2018-12-18) to Version v12.0p_2019-02-12/PowerEdition Deployment (2019-02-12)
              Last edited by mabboud; 22 Feb 2019, 05:50.

              Comment


                #8
                Apologies for the silence on this one. The problem here isn't actually anything to do with your custom type, or the grid being nested in a formItem.

                It's actually a focus issue arising from your use of recordComponents and saveLocally - we're looking into that.

                In the meantime, note that recordComponents are not especially efficient, given that the mechanism automatically creates and updates widgets in various circumstances.

                Since your recordCompponents in this case simply remove the record they're attached to, is there any reason you don't just get rid of the recordComponents and instead set grid.canRemoveRecords: true? That would show the builtin removeField, which is icon-based (so more efficient) and does exactly what your record component does.

                Comment


                  #9
                  for simplicity of the test case i removed my logic for the recordComponents .... i am doing more with the recordComponents

                  Code:
                              gridRecordComponent:function (record, colNum) {
                                  if ( record.currentStatusKey == 2 || record.currentStatusKey == 3)
                                      return null;
                                  if ( record.isGroupSummary )
                                      return null;
                                  var fieldName = this.getFieldName(colNum);
                                  if (fieldName == "removeItemBtn") {
                                      var button = isc.IButton.create({
                                          height: 18,
                                          width: 25,
                                          icon: "general_delete.png",
                                          title: "",
                                          click : function () {
                                              requestForm.getItem("items").canvas.removeData(record);
                                          }
                                      });
                                      return button;
                                  } else if (fieldName == "editItemBtn") {
                                      var button = isc.IButton.create({
                                          height: 18,
                                          width: 25,
                                          icon: "general_edit.gif",
                                          title: "",
                                          click : function () {
                                              addItemForm.editRecord(record);
                                              addItemForm.originalRecord=record;
                                              requestForm.getItem("items").canvas.removeData(record);
                                              addItemForm.getField('rollstockSupplierKey').canEdit=false;
                                              addItemWindow.show();
                                          }
                                      });
                                      return button;
                                  } else {
                                      return null;
                                  }
                              }

                  Comment


                    #10
                    [Edit]

                    Ah, we see that you're showing a popout editor - you could do this more efficiently with a single custom icon field with a formatter and a click-handler.

                    But we'll fix the underlying bug (which is a focus issue arising from inline saving in the presence of recordComponents) and let you know when the fix hits the builds.
                    Last edited by Isomorphic; 3 Mar 2019, 00:23.

                    Comment


                      #11
                      not sure what do u mean by " single custom icon field with a formatter and a click-handler. " would u give out an example of this please


                      i am just following ur example on how to add Cell Widgets :

                      https://www.smartclient.com/smartcli...ridCellWidgets


                      thanks you

                      Comment


                        #12
                        If you're adding two recordComponent fields, and showing both buttons at once per row, then granted, you can't use a single icon field - but you can use 2 of them, or switch on canRemoveRecords (which will add one icon field) and add your own custom one for your Edit-feature.

                        See the docs for listGridField.cellIcon - you just need a field of type "icon", that specifies icon and/or cellIcon and implements recordClick().

                        That would be more efficient, especially if you have lots of rows - but we'll let you know when the problem with recordComponents is fixed, if you want to continue on that road.

                        Also, note that, whether you use recordComponents or icons, your custom fields will probably want to switch off, in your case, at least canEdit - and canFilter and similar settings according to your other config.

                        Comment


                          #13
                          This recordComponent-related focus issue has now been resolved - you can retest with a build dated March 13 or later.

                          Comment


                            #14
                            The error is resolved but this is still not working i took the code from #3 and applied it to your show case when i enter values the first one sticks but editing any other value in the ListGrid doesn't save the changes check the following :

                            Click image for larger version

Name:	NestedListGridEditing2.gif
Views:	112
Size:	596.1 KB
ID:	257158

                            Comment


                              #15
                              We're not seeing this behavior if we drop your sample into the latest online showcase, dated March 14 - it's possible the change didn't hit the build queue in time for the March 13 builds, but it's there now.

                              Please retest.

                              Comment

                              Working...
                              X