最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

asp.net core - Add Class When Button Is Clicked While Other Buttons Are Present On Page In Blazor - Stack Overflow

programmeradmin1浏览0评论

I can't seem to solve this without using integers or different class or event names per button (which isn't scalable). I have a custom ripple-effect that I've created in Blazor and need each button on the page to receive a "ripple" class when clicked and then remove that class after a second or two.

@using System.Timers
<button class="primary-btn @buttonClass" @onclick="AddRipple">Action 1</button>
<button class="primary-btn @buttonClass" @onclick="AddRipple">Action 2</button>
@code {
    // Set Ripple Class
    private string buttonClass = "";
    private void AddRipple()
    {
        buttonClass = "ripple";
        StartTimer();
    }
    private void StartTimer()
    {
        var timer = new Timer(1000);
        timer.Elapsed += RemoveClass;
        timer.AutoReset = false;
        timer.Start();
    }
    private void RemoveClass(object source, ElapsedEventArgs e)
    {
        buttonClass = "";
        ((Timer)source).Dispose();
        InvokeAsync(StateHasChanged);
    }
}

I have created and tested this functionality, but it applies the class change to every button on the page when any one button is clicked. How can I make the event fire and apply only the class change on the actual button clicked?

--UPDATE-- I created a custom razor component and that worked beautifully. I should have realized that! DOH! Here is a step by step guide if anyone is new at this like me:

I can't seem to solve this without using integers or different class or event names per button (which isn't scalable). I have a custom ripple-effect that I've created in Blazor and need each button on the page to receive a "ripple" class when clicked and then remove that class after a second or two.

@using System.Timers
<button class="primary-btn @buttonClass" @onclick="AddRipple">Action 1</button>
<button class="primary-btn @buttonClass" @onclick="AddRipple">Action 2</button>
@code {
    // Set Ripple Class
    private string buttonClass = "";
    private void AddRipple()
    {
        buttonClass = "ripple";
        StartTimer();
    }
    private void StartTimer()
    {
        var timer = new Timer(1000);
        timer.Elapsed += RemoveClass;
        timer.AutoReset = false;
        timer.Start();
    }
    private void RemoveClass(object source, ElapsedEventArgs e)
    {
        buttonClass = "";
        ((Timer)source).Dispose();
        InvokeAsync(StateHasChanged);
    }
}

I have created and tested this functionality, but it applies the class change to every button on the page when any one button is clicked. How can I make the event fire and apply only the class change on the actual button clicked?

--UPDATE-- I created a custom razor component and that worked beautifully. I should have realized that! DOH! Here is a step by step guide if anyone is new at this like me: https://toxigon/building-reusable-components-in-blazor

Share Improve this question edited Mar 14 at 13:46 jottin asked Mar 14 at 0:59 jottinjottin 4312 silver badges13 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

Your thinking about this the wrong way. Build the functionality into a custom button component. Totally scalable.

Here's a demo MyButton component that changes colour for 2 seconds. It uses the primitive System.Threading.Timer to load a one time timer task onto the application timer. When this expires it calls OnTimerExpired which renders the component. The component implements IDisposable to clear down any running timers when the component is disposed.

@implements IDisposable

<button class="@_buttonClass" @onclick="AddRipple">@ChildContent</button>

@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public EventCallback OnClick { get; set; }

    private IDisposable? _disposer;
    private bool _rippling;
    private string _buttonClass => _rippling ? "btn btn-danger" : "btn btn-success";

    private async Task AddRipple()
    {
        _rippling = true;
        _disposer = new System.Threading.Timer(this.OnTimerExpired, null, TimeSpan.FromSeconds(2), TimeSpan.Zero);
        await OnClick.InvokeAsync();
    }

    private void OnTimerExpired(object? data)
    {
        _rippling = false;
        this.InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        _disposer?.Dispose();
    }
}

See https://shauncurtis.github.io/Posts/Timers.html for more detailed info on timers.

From my understanding you need a list to control the state of each button class which uses independent timer.

@page "/"
<style>
    .ripple{
    color:red;
    }
</style>

@using System.Timers
<button  class="primary-btn @buttonClass[1]" @onclick="()=>AddRipple(1)">Action 1</button>
<button  class="primary-btn @buttonClass[2]" @onclick="()=>AddRipple(2)">Action 2</button>

@code {
    //create list of 3 items to match index 1 and 2.
    private List<string> buttonClass = new List<string>(new string[3]);

    private void AddRipple(int i)
    {
        buttonClass[i] = "ripple";
        StartTimer(i);
    }
    private void StartTimer(int i)
    {
        var timer = new Timer(1000);
        timer.Elapsed += (sender,e)=> RemoveClass(sender,e,i);
        timer.AutoReset = false;
        timer.Start();
    }
    private void RemoveClass(object source, ElapsedEventArgs e,int i)
    {
        buttonClass[i] = "";
        ((Timer)source).Dispose();
        InvokeAsync(StateHasChanged);
    }
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论