TWebGridPanel by code: First added control starts in second column

I am using latest version of TMS Web Code [v2.8.1.0] and try to create TWebGridPanel by code. I have made a simple project to illustrate the problem:

I use a TWebPageControl, creates a TWebScrollBox on each page, and creates a TWebGridPanel in the scollbox using an array of gridpanels. I create 3 columns for each grid. The left column should contain a red panel, the middle one a green one, and the right on should contain a yellow panel.
The problem is that the first AddControl(pnlLeft) starts in column 1, not column 0. Help appreciated!

type
  TForm1 = class(TWebForm)
    WebPanel1: TWebPanel;
    WebPageControl1: TWebPageControl;
    WebPageControl1Sheet1: TWebTabSheet;
    AddPageButton: TWebButton;
    procedure WebFormCreate(Sender: TObject);
    procedure AddPageButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    gpArray: array of TWebGridPanel;
    function AddPageAndGrid(date: TDateTime): Integer;
    procedure FillGridOnPage(tabIdx: Integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.AddPageAndGrid(date: TDateTime): Integer;
var
  i: Integer;
  sBox: TWebScrollBox;
begin
  i := Length(gpArray);
  SetLength(gpArray,i+1);
  WebPageControl1.Items.Add(FormatDateTime('ddd d/m',date));
  sBox := TWebScrollBox.Create(Self);
  sBox.Parent := WebPageControl1.Pages[i];
  sBox.Align := alClient;
  gpArray[i] := TWebGridPanel.Create(Self);
  gpArray[i].Parent := sBox;
  gpArray[i].Align := alTop;
  gpArray[i].Height := 500;

  gpArray[i].ColumnCollection.Clear;
  gpArray[i].ColumnCollection.Add;
  gpArray[i].ColumnCollection.Add;
  gpArray[i].ColumnCollection.Add;

  gpArray[i].RowCollection.Clear;
  Result := i;
end;

procedure TForm1.FillGridOnPage(tabIdx: Integer);
var
  i: Integer;
  pnlLeft,pnlRight,pnlMiddle: TWebPanel;
begin
  for i := 0 to 5 do begin
     gpArray[tabIdx].RowCollection.Add;
     gpArray[tabIdx].RowCollection.Items[gpArray[tabIdx].RowCollection.Count-1].SizeStyle := ssAbsolute;
     gpArray[tabIdx].RowCollection.Items[gpArray[tabIdx].RowCollection.Count-1].Value := 20;

     pnlLeft := TWebPanel.Create(Self);
     pnlLeft.Align := alTop;
     pnlLeft.Height := 20;
     pnlLeft.Color := clRed;
     gpArray[tabIdx].AddControl(pnlLeft);

     pnlMiddle := TWebPanel.Create(Self);
     pnlMiddle.Align := alTop;
     pnlMiddle.Height := 20;
     pnlMiddle.Color := clGreen;
     gpArray[tabIdx].AddControl(pnlMiddle);

     pnlRight := TWebPanel.Create(Self);
     pnlRight.Align := alTop;
     pnlRight.Height := 20;
     pnlRight.Color := clYellow;
     gpArray[tabIdx].AddControl(pnlRight);
  end;
end;

procedure TForm1.WebFormCreate(Sender: TObject);
var
  tabIdx: Integer;
begin
  WebPageControl1.BeginUpdate;
  WebPageControl1.Items.Clear;
  tabIdx := AddPageAndGrid(Now);
  FillGridOnPage(tabIdx);
  WebPageControl1.EndUpdate;
end;

procedure TForm1.AddPageButtonClick(Sender: TObject);
var
  tabIdx: Integer;
begin
  WebPageControl1.BeginUpdate;
  tabIdx := AddPageAndGrid(Now);
  FillGridOnPage(tabIdx);
  WebPageControl1.EndUpdate;
end;


Output
image

Project files
TestGridOnPages.dpr (305 Bytes)
TestGridOnPages.dproj (57.7 KB)
TestGridOnPagesProject.html (643 Bytes)
TestGridOnPagesUnit.dfm (880 Bytes)
menudemo.html (195 Bytes)
TestGridOnPagesUnit.pas (2.8 KB)

Change your code to:

procedure TForm1.AddGridOnPage(tabIdx: Integer);
var
  i: Integer;
  pnlLeft,pnlRight,pnlMiddle: TWebPanel;
begin
  for i := 0 to 5 do
  begin
     gpArray[tabIdx].RowCollection.Add;
     gpArray[tabIdx].RowCollection.Items[gpArray[tabIdx].RowCollection.Count-1].SizeStyle := ssAbsolute;
     gpArray[tabIdx].RowCollection.Items[gpArray[tabIdx].RowCollection.Count-1].Value := 20;

     pnlLeft := TWebPanel.Create(nil);
     pnlLeft.Align := alTop;
     pnlLeft.Height := 20;
     pnlLeft.Color := clRed;
     gpArray[tabIdx].AddControl(pnlLeft);

     pnlMiddle := TWebPanel.Create(nil);
     pnlMiddle.Align := alTop;
     pnlMiddle.Height := 20;
     pnlMiddle.Color := clGreen;
     gpArray[tabIdx].AddControl(pnlMiddle);

     pnlRight := TWebPanel.Create(nil);
     pnlRight.Align := alTop;
     pnlRight.Height := 20;
     pnlRight.Color := clYellow;
     gpArray[tabIdx].AddControl(pnlRight);
  end;
end;

Thanks! So such components have to be freed manually then. Is there any "rules" as to when we should use Create(nil) instead of Create(Self) in Web Core?

One more thing and we are good: When I refresh a page (I use the grid to display json objects from server), some empty lines are displayed at the top. Modified code (I now use a panelArray: array of TWebPanel; to store panels that must be freed manually):

procedure TForm1.FillGridOnPage(tabIdx: Integer);
var
  i,j,pnlIdx: Integer;
begin
  pnlIdx := Length(panelArray);
  for i := 0 to 5 do begin
     gpArray[tabIdx].RowCollection.Add;
     gpArray[tabIdx].RowCollection.Items[gpArray[tabIdx].RowCollection.Count-1].SizeStyle := ssAbsolute;
     gpArray[tabIdx].RowCollection.Items[gpArray[tabIdx].RowCollection.Count-1].Value := 20;

     SetLength(panelArray,pnlIdx+3);
     for j := 0 to 2 do begin
       panelArray[pnlIdx] := TWebPanel.Create(nil);
       panelArray[pnlIdx].Align := alTop;
       panelArray[pnlIdx].Height := 20;
       if j = 0 then
         panelArray[pnlIdx].Color := clRed
       else if j = 1 then
         panelArray[pnlIdx].Color := clGreen
       else
         panelArray[pnlIdx].Color := clYellow;
       gpArray[tabIdx].AddControl(panelArray[pnlIdx]);
       Inc(pnlIdx);
     end;
  end;
end;

procedure TForm1.RefreshPageBtnClick(Sender: TObject);
var
  i,pgIdx: Integer;
begin
  WebPageControl1.BeginUpdate;
  pgIdx := WebPageControl1.ActivePageIndex;
  for i := 0 to Length(panelArray) do
     panelArray[i].Free;
  SetLength(panelArray,0);
  gpArray[pgIdx].RowCollection.Clear;
  FillGridOnPage(pgIdx);
  WebPageControl1.EndUpdate;
end;

Output after refresh:

(I know that code only works for one page). I can work around this last refresh-issue by freeing the TWebGridPanel-array and recreate it, but thought I should mention it anyway.

Did you try to call

webgridpanel.ControlCollection.Clear;

before filling the TWebGridPanel again?

Great! Thanks again. Can you confirm that I have to free the panels manually because of Create(nil), or will the be freed with the webgridpanel due to AddControl(panel)?

The TWebGridPanel will not destroy controls itself.