目前的4篇日誌是來自我們寫好的假資料,但正常來說不會這樣做,而是有顆按鈕讓使用者按了之後,增加或減少日誌的數量。
增加的按鈕會放在<Blog>
,按了「增加」按鈕產生一筆新的Post供使用者輸入,再讓使用者點擊「確認」按鈕儲存日誌。
刪除的按鈕則可以放在<Blog>
,再於<Post>
加入checkbox,讓使用者自己勾選要刪除哪些Post;或是放在<Post>
,按下刪除按鈕就刪除該筆日誌。
新增按鈕很簡單,只要在<MyButton>
加上@onclick
事件即可,開始之前,先將版面稍作修改,順便把FontSizeStyle
移除。
C#部分則加入add()
方法,原本loadData()
的日誌刪除。
接著點擊Add按鈕,就可以看到日誌筆數增加了。
接著來做Delete功能,在Post.razor
加入Delete按鈕。
但問題來了,當我按下Delete按鈕,<Blog>
怎麼知道我刪除的是哪一筆Post?這時候就需要PostId可以識別,於是加入一個私有變數postId
,每次按下add()
都+1,正常來說PostId會跟著Post而不是由Blog產生,不過因為還沒接觸到資料庫,所以先這樣將就,未來連接資料庫後就會改變。
為了驗證是否正確,刪除原本Post.razor
註解的Post.Id
,加入新樣式的Post.PostId
,可以看到沒有問題。
現在有了識別PostId,又產生了新問題,要怎麼讓<Blog>
收到PostId?目前PostId由<Blog>
產生,所以沒這問題,等未來PostId由資料庫產生後,<Blog>
就不會知道PostId了。前面說的都是從Parent component傳遞資料到Child component的方法,我們現在要從Child component傳資料到Parent component,有辦法做到反向傳回去嗎?
有的,那就是EventCallback,但是要把Delete改成<input>
而非<MyButton>
,因為EventCallback是由Child傳向Parent,如果用<MyButton>
,PostId的流向就必須先這樣 <Blog>
=><Post>
=><MyButton>
,接著再用EventCallback反向<MyButton>
=><Post>
=><Blog>
,實在太麻煩了。
先把Delete按鈕改成<input>
,加入@onclick="returnPostId"
。
接著在Post.razor.cs
定義型別為EventCallback<int>
的Property getPostId
,記住一定要加上[Parameter]
attribute,因為這要讓<Blog>
呼叫。然後完整定義returnPostId()
方法,裡面做的就是getPostId.InvokeAsync(Post.PostId);
,當外部傳來的getPostId被觸發時,就將Post.PostId
傳給Parent也就是<Blog>
。
再於Blog.razor.cs
定義同名方法getPostId(int id)
,名字不需要一樣,這邊只是為了方便取同名,裡面做的事情就是移除跟收到的PostId有相同值的Post。
最後在Blog.razor
的<Post>
的getPostId
放入剛剛定義的方法就可以了。
我們來實驗看看,先新增4筆日誌,再刪除第2筆,可以看到Post Id等於2的那筆成功被刪除了。
除了EventCallback,還有Delegate可以使用,不過侷限性較大,我們也來試試看。
先在Post.razor.cs
定義型別為Action<int>
的Property getPostIdForDelegate
,returnPostId()
改用getPostIdForDelegate
。
接著在Blog.razor
的<Post>
改用getPostIdForDelegate
。
但是真的點擊後會發現不會刪除日誌,這是因為EventCallback會監控Component,一旦有異動就會重新render,Delegate則不會,Delegate必須在Parent component也就是Blog.razor.cs
呼叫StateHasChanged();
方法,讓Parent component知道狀態改變了。
另外Delegate一旦在Child component定義了,Parent component就必須要叫用,否則會發生錯誤,EventCallback則沒這問題。
Ref: Blazor EventCallback
Ref: EventCallback
Ref: Blazor Tutorial - Ep11 - EventCallback and how it is different from delegate