Jurioli / Blazor.WebForm.Components

ASP.NET Web Forms System.Web.UI.WebControls Razor Components For Blazor WebAssembly, Blazor Hybrid, Blazor Server.
MIT License
44 stars 9 forks source link

Order of lifecycle events #11

Closed MG1376 closed 5 months ago

MG1376 commented 5 months ago

I used this code for page lifecycle:

@page "/mypage"
@inherits ControlComponent

<asp.TextBox ID="Val" TextMode="UI.TextBoxMode.Date" @ref="this.myval">
</asp.TextBox>
<asp.Button Text="Add" OnClick="this.AddButton_Click" />
<h1>@res.ToString()</h1>

<h1>@msg</h1>

@code {

    string msg = "";

    protected override void OnInitialized()
    {
        this.Control.Init += OnInit;
        this.Control.PreRender += OnPreRender;      
        base.OnInitialized();
    }

    public void OnInit(object sender, EventArgs e)
    {
        msg += "Init, ";
    }

    protected override void OnLoad(object sender, EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            msg += "First Load, ";
        }
        else
        {
            msg += "Postback Load, ";          
        }
    }

    public void OnPreRender(object sender, EventArgs e)
    {
        msg += "Prerender, ";    
    }

    UI.TextBox myval = null;
    DateTime? res = null;
    protected void AddButton_Click(object sender, EventArgs e)
    {
        res = Convert.ToDateTime(myval.Text);
        msg += "Click Handler, ";
        this.RequestRefresh();
        StateHasChanged();
    }

    protected override void OnUpdate(object sender, StateUpdateEventArgs e)
    {
        // how to use this?
        base.OnUpdate(sender, e);
        dialogService.Alert("Update.");
    }

But the order of events that are fired is: Init, First Load, Prerender, Click Handler, Postback Load, Prerender, It should be: Init, First Load, Prerender, Postback Load, Click Handler, Prerender,

Is this by design? since asp.net click and change events are fired between load and prerender events.

Jurioli commented 5 months ago

There is no way to migrate it exactly the same as the original lifecycle. It becomes an independent page lifecycle for each ControlComponent.

OnUpdate is the event that triggers the execution of StateHasChanged.

When clicking, only the page lifecycle of Button is executed and then other components update render are notified.

@page "/mypage"
@using System.Web.UI
@using System.Web.UI.WebControls
@inherits ControlComponent

<asp.TextBox ID="Val" TextMode="TextBoxMode.Date" @ref="this.myval">
</asp.TextBox>
<asp.Button _ref="() => this.button" Text="Add" OnClick="this.AddButton_Click" />
<h1>@res?.ToString()</h1>

<h1>
    <asp.Label _ref="() => this.msg" />
</h1>

@code {
    Button button = new Button();
    Label msg = new MsgLabel();

    protected override void OnInitialized()
    {
        this.Control.Init += Control_OnInit;
        this.Control.Load += Control_OnLoad;
        this.Control.PreRender += Control_OnPreRender;
        button.Init += Button_OnInit;
        button.Load += Button_OnLoad;
        button.PreRender += Button_OnPreRender;
        base.OnInitialized();
    }

    public void Control_OnInit(object sender, EventArgs e)
    {
        msg.Text += "Init (Control), ";
    }

    public void Button_OnInit(object sender, EventArgs e)
    {
        msg.Text += "Init (Button), ";
    }

    protected void Control_OnLoad(object sender, EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            msg.Text += "First Load (Control), ";
        }
        else
        {
            msg.Text += "Postback Load (Control), ";
        }
    }

    protected void Button_OnLoad(object sender, EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            msg.Text += "First Load (Button), ";
        }
        else
        {
            msg.Text += "Postback Load (Button), ";
        }
    }

    public void Control_OnPreRender(object sender, EventArgs e)
    {
        msg.Text += "Prerender (Control), ";
    }

    public void Button_OnPreRender(object sender, EventArgs e)
    {
        msg.Text += "Prerender (Button), ";
    }

    TextBox myval = null;
    DateTime? res = null;
    protected void AddButton_Click(object sender, EventArgs e)
    {
        res = Convert.ToDateTime(myval.Text);
        msg.Text += "Click Handler, ";
        // this.RequestRefresh();
        StateHasChanged();
    }

    protected override void OnUpdate(object sender, StateUpdateEventArgs e)
    {
        // how to use this?
        base.OnUpdate(sender, e);
        // dialogService.Alert("Update.");
    }

    public class MsgLabel : Label
    {
        protected override void Render(HtmlTextWriter writer)
        {
            this.Text += "Render (Label), ";
            base.Render(writer);
        }
    }
}

Init (Control), First Load (Control), Prerender (Control), Init (Button), First Load (Button), Prerender (Button), Render (Label), Postback Load (Button), Click Handler, Render (Label), Prerender (Button), Render (Label),