In this section we are gonna enable users to add, modify and delete their shifts

Event Handling & Data Binding

When the user clicks the add button an add shift dialog should pop up to allow the user to enter the new shift information.

In Blazor handling DOM UI events is pretty easy, you specify wich event you want to handle using the corresponding HTML attribute and then specify the C# delegate you want called. The delegate may optionally take an event specific argument, but it’s not required.

In Pages/Index.cshtml add a button with the following onclick handler to the add a new shift.

 <button onclick="@(() => Console.WriteLine("Add a new Shift"))" class="btn btn-outline-primary my-2 my-sm-0 add-shift-btn" type="button"><i class="fas fa-plus-square"></i></button>

If you run the app, every time you click the add shift button it will print “Add a new Shift” to the VS console.

The @ symbol comes from Razor, it indicate the start of C# code. Lets update the function block in Index.cshtml, lets add some values. We will add a ConfiguredShift, this this will be the object provided to the component that will be in charge of editing the object. The ShowShiftEditor will trigger the component itself.

    protected Shift ConfiguredShift { get; set; }
    private bool ShowShiftEditor { get; set; } = false;

Add a AddNewShift method to the function block, this will be trigger when the user click the add new shift button.

  protected void AddNewShift()
    {
        ConfiguredShift = new Shift();
        ShowShiftEditor = true;
        StateHasChanged();
    }

Update the onclick handler to call the AddNewShift method instead of Console.WriteLine.

<button onclick="@AddNewShift" class="btn btn-outline-primary my-2 my-sm-0 add-shift-btn" type="button"><i class="fas fa-plus-square"></i></button>

Shift Editor Component

Now we create a component that will handle any modification to a shift, will make this component generic, that way it can be use to add or edit a shift. The component should let the user specify a title, description, time and will let you add the shift to the story or modify it.

Add a ShiftEditorComponent.cshtml file under Shared/Component I like to put my components inside its own folder. Since this component is not a separate page, it does not need the @page directive.

The ShiftEditorComponent should have a parameter that specifies the shift being configured, we will call it Shift, we will also add a Title property so our component can have a dynamic title. Component parameters are defined by adding a writable property to the component decorated with the [Parameter] attribute

@functions{

   [Parameter] protected String Title { get; set; } = "Shift Editor";
    [Parameter]  Shift Shift { get; set; } = new Shift();
  
}


Note: Component parameters values should only ever be set by the runtime, so they should not be public. This allows the runtime to keep track of when components need to be rendered.

The user should be able to specify the name, a description and the start and end time of the shift. We can use data binding to bind the value of the properties to the value of the html elements. knowing this we now can add some markup:

<div class="modal fade show modal-display" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalCenterTitle">@Title</h5>
               
            </div>
            <div class="modal-body">
                <form>


                    <div class="form-group row">
                        <label for="colFormLabel" class="col-sm-4 col-form-label">Title</label>
                        <div class="col-sm-8">
                            <input bind="@Shift.Name" type="text" class="form-control" id="colFormLabel" placeholder="Type a title for the shift" />
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="colFormLabel" class="col-sm-4 col-form-label">Description</label>
                        <div class="col-sm-8">
                            <input type="text" bind="@Shift.Description" class="form-control" id="colFormLabel" placeholder="What did your work on this time..." />
                        </div>
                    </div>

                    @* We will ask user for start and end date and time *@
                    <div class="form-group row">
                        <label for="example-datetime-local-input" class="col-sm-4 col-form-label">Start Time</label>
                        <div class="col-sm-8">
                            <input class="col-sm-12 form-control" bind="@Shift.StartTime" type="datetime-local" value="2011-08-19T13:45:00" id="example-datetime-local-input" />
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="example-datetime-local-input" class="col-sm-4 col-form-label">End Time</label>

                        <div class="col-sm-8">
                            <input class="col-sm-12 form-control" bind="@Shift.EndTime" type="datetime-local" value="2011-08-19T13:45:00" id="example-datetime-local-input" />
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" onclick="" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
                <button type="button" onclick="" class="btn btn-primary">Save changes</button>
            </div>
        </div>
    </div>
</div>


Data binding in Blazor allows for this by letting you specify what value you want to bind to and what event triggers a change using the syntax bind-<value>-<event>.

Now we will update Index.cshtml to show our component

@if (ShowShiftAdd)
        {
            <ShiftEditorComponent Title="Add New Shift" Shift="@ConfiguredShift" ></ShiftEditorComponent>
        }

Run the app and when the user click on add new shift the new editor should appear


Component Events

Component Events help component comminucate wiht other componentsThe Cancel and Save Changes don’t do anything yet. Component events are action parameters that parent components can subscribe to.

lets add two parameters to the ShiftEditorComponent:
OnCancel and OnConfirm. Both parameters should be of type Action.

 [Parameter] protected String Title { get; set; } = "Shift Editor";
    [Parameter] protected Action OnCancel { get; set; }
    [Parameter] protected Action OnConfirm { get; set; }
    [Parameter]  Shift Shift { get; set; } 

We can now add onclick event handlers to the buttons of our components that triggers OnCancel and OnConfirmation events.

  <div class="modal-footer">
                <button type="button" onclick="@OnCancel" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
                <button type="button" onclick="@OnConfirm" class="btn btn-primary">Save changes</button>
            </div>

In the Index component add an event handler for the OnCancel and OnConfirm event that hides the dialog and wires it up to the ShiftEditor.

<ShiftEditorComponent Title="Shift Editor" Shift="@ConfiguredShift" OnCancel="@HideShiftEditorBtnClick" OnConfirm="@SaveEditedShift"></ShiftEditorComponent>

we will create three methods, two of those will be the event, and the third will be incharge of adding the new shift.

protected void SaveEditedShift()
    {
        if(ConfiguredShift.Id == -1)
        {
            ConfiguredShift.Id = NewID();
            history.Add(ConfiguredShift);
        }
        else
        {
            var index = history.FindIndex(x => x.Id == ConfiguredShift.Id);
            history[index] = ConfiguredShift;
        }

        ShowShiftEditor = false;
        StateHasChanged();

    }

    protected void AddNewShiftBtnClick()
    {
        ConfiguredShift = new Shift();
        ShowShiftAdd = true;
        StateHasChanged();
    }



    protected void HideShiftEditorBtnClick()
    {
        ShowShiftAdd = false;
        ShowShiftEditor = false;
        StateHasChanged();
    }

The StateHasChanged method signals to the runtime that the component’s state has changed and it needs to be rendered. Components are rendered automatically by the runtime when its parameters change or when a UI event is fired on that component. In this case the event triggering the state change came from a different component, so StateHasChanged needs to be called manually.

Run the app and verify that the dialog now disappears when the Cancel button is clicked.

When the OnConfirm event is fired, the comfigure Shift should be added, if the shift already exist it will be rewrite to asign the new changes.

Since we use binding in the index to display the shift, once we add a shift it will populate in the index.

Next we will address routes and navlinks.