My RowCreated event handler causes the grid to add new rows twice

4 posts, 1 answers
  1. Ashraf Sabry
    Ashraf Sabry avatar
    88 posts
    Member since:
    Jan 2011

    Posted 11 Dec 2013 Link to this post


    I'll try to be clear as possible in describing this problem as I couldn't catch its cause until I did long debugging inside Rad controls' code.

    What I'm trying to create is a serial column (1, 2, 3, …) that keeps its proper serialing with the user deleting from and adding to the grid in batch mode.
    The logic is very simple. I added a handler to the RowCreated event as follows:

    grid.add_rowCreated(function (sender, args)
            var item = args.get_item();
                Edge.UI.GridExtensions.setCellValue(item, uniqueName, Edge.UI.GridExtensions.SerialColumn.getMaxSerialValue(tableView, uniqueName) + 1);
    Edge.UI.GridExtensions.SerialColumn.getMaxSerialValue = function (tableView, uniqueName)
        var max = Number.NEGATIVE_INFINITY,
            dataItems = tableView.get_dataItems();
        if(dataItems && dataItems.length)
            for(var i = dataItems.length; i--;)
                var value = parseInt(Edge.UI.GridExtensions.getCellValue(dataItems[i], uniqueName));
                if(value > max)
                    max = value;
        return max === Number.NEGATIVE_INFINITY ? 0 : max;

    The relevant part is the line marked with bold and italic (dataItems = tableView.get_dataItems())

    Here's the sequence I do to reproduce the problem:
    1. I start with an empty grid, then click the "Add New" button.
    2. The button calls BatchEditingManager.addNewRecord which in turn calls GridTableView.createItem.
    3. createItem creates the TR element and appends it to the DOM and creates a GridDataItem object for it.
    4. Then, near the end of the method body, come two lines of code who cause the problem:
      p._owner.raise_rowCreated(new Telerik.Web.UI.GridDataItemEventArgs(n, null));
      Array.insert(e, k, d);
      I extracted these from the minified code with the usage of chrome developer tools' pretty print feature. You may find them using the find functionality of your text editor. The first line calls my event handler, which calls get_dataItems (the line in bold in the first code block). Inside get_dataItems the code checks the length of the internal _dataItems array:
      if (this._dataItems.length > 0 || (this._cachedItems && this._cachedItems.length > 0)) {
                  return this._dataItems;
      Of course it finds the length equal to zero because the GridDataItem object wasn't added to the array yet in createItem. The code then goes into initialising the _dataItems array from the TR elements:
      var o = ($telerik.isOpera) ? this.get_element() : this.get_element().tBodies[0];
              var n = o.rows;
              for (var c = 0, k = n.length;
              c < k;
              c++) {
                  this._owner.raise_rowCreating(new Sys.EventArgs());
                  if (!b) {
                      b = $create(Telerik.Web.UI.GridDataItem, {_owner: this,_data: a}, null, null, m);
                  this._dataItems[this._dataItems.length] = b;
                  this._owner.raise_rowCreated(new Telerik.Web.UI.GridDataItemEventArgs(m, null));
      I replaced the irrelevant parts with ellipsis. This code adds a GridDataItem object to the array then raises the RowCreated event (which is the proper behaviour), but I wonder why isn't the event raised inside the if(!b) block? If the b object exists from a previous initialisation, why raising the RowCreated event for it again? The last piece of code causes my event handler to be called again and my serial result to be wrongly evaluated (it returns 2 instead of one), but this is not the main problem.
    5. After all that code executes, the _dataItems array now have two objects for the same TR element (one created by createItem and the other created by the get_dataItems accessor), if I remove the single grid row using BatchEditingManager.deleteRecord the grid remains with an orphan GridDataItem object.

    After this, the grid stops working. When I try adding new lines, an exception erupts. I don't know certainly the cause, but it should be because of the orphan item.

    After the description of the problem, I'd like to say that some accessors in the Rad controls code involve a lot of work which shouldn't be the nature of accessors. I have some places where get_dataItems raises exceptions, and I had no means to avoid but a nasty dummy try/catch

            gridDataItems = this.tableView.get_dataItems();
        } catch(dummy)
        { }

  2. Ashraf Sabry
    Ashraf Sabry avatar
    88 posts
    Member since:
    Jan 2011

    Posted 11 Dec 2013 Link to this post

    I understand that the get_dataItems accessor tries to do lazy initialisation, but it should do it once based on a flag not on _dataItems.length, because this way, it will do the initialisation more than once. If the user deleted all the rows then get_dataItems is called, the initialisation code again will be called again.
  3. Answer
    Angel Petrov
    Angel Petrov avatar
    1039 posts

    Posted 16 Dec 2013 Link to this post

    Hello Ashraf,

    Indeed such a problem does exist in the current version of the controls and is already logged into our system. Our developers will try to include a fix for it as soon as possible.

    As for the get_dataItems call and the throwing of the error I would like to ask you to describe a scenario(apart from the mentioned one) in which it can be observed. That way we will be able to investigate what it causing this behavior.

    Angel Petrov
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
  4. Ashraf Sabry
    Ashraf Sabry avatar
    88 posts
    Member since:
    Jan 2011

    Posted 17 Dec 2013 Link to this post

    I've commented the try-catch blocks and will inform you about the problem if it happened again.
Back to Top