Is there a way to implement JavaScript within my Blazor server razor page to modify the styling of a blazor bootstrap button after a form submission?

I am currently working on a Blazor server application where I am looking to add a special functionality. My goal is to have the accordion header change to red if validation fails, meaning if there is no input in the field.

view image here

//index.razor page:

@page "/"
<style>


</style>
<PageTitle>Blazor Bootstrap - Home</PageTitle>
<div class="test1">
    <EditForm Model="@registration" OnValidSubmit="HandleFormSubmission">
        <DataAnnotationsValidator />
        <Accordion>
            <AccordionItem Title="Accordion Item #1">
                <Content>
                    <InputText id="SmtpHost" @bind-Value="@registration.SmtpHost" placeholder="SMTP Host" />
                    <ValidationMessage For="@(() => registration.SmtpHost)" />
                </Content>
            </AccordionItem>
        </Accordion>
        <button type="submit">Submit</button>
    </EditForm>
</div>

@code {
    [Inject]
    protected IJSRuntime JSRuntime { get; set; }
    Data.Registration registration = new();
    bool isValidationError = false;
    bool isFormSubmitted = false;
    bool hasRendered = false;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
                // await Task.Yield();
                // await ToggleAccordionButtonError();
        }
    }

    public async Task HandleFormSubmission(EditContext context)
    {
        Console.WriteLine("Form Submitted Successfully");
        isValidationError = !context.Validate();

        Console.WriteLine("Testing");
        Console.WriteLine(isValidationError);

        if (isValidationError)
        {
            isFormSubmitted = true;
            if (hasRendered)
            {
                ToggleAccordionButtonError();
            }
            else
            {
                StateHasChanged(); // Notify Blazor to re-render the component
            }
        }
    }

    private async Task ToggleAccordionButtonError()
    {
        try
        {
            await JSRuntime.InvokeVoidAsync("toggleAccordionButtonError");
            await JSRuntime.InvokeVoidAsync("myJavaScriptFunction");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error invoking JavaScript function: {ex.Message}");
        }
    }
}

custom.js content:

console.log("File recognised");

function myJavaScriptFunction() {
    // Invoke an alert
    console.log("Hello from JavaScript!");
}

// .test1 .accordion-button
function toggleAccordionButtonError() {
    console.log("Hello from JavaScript!");
    var elements = document.querySelectorAll('.accordion-button.collapsed');
    elements.forEach(function (element) {
        element.style.backgroundColor = "red";
        element.style.color = "white";
    });
}

The custom.js file works as intended, even though some code is commented out. One potential solution I considered was using Javascript interop with HandleFormSubmission, but it did not work as expected. I understand that Blazor's Prerendering feature may impose restrictions on when JavaScript interop calls can be made. If anyone has insights or workaround solutions for this issue, I would greatly appreciate it.

Answer №1

It may not be advisable to rely on JS Interop for this particular task.

If you are aiming for fields to turn red upon validation failure, the CSS class invalid will automatically be applied to the respective input element when invalid. This can also be verified in the Dev Tools. A possible styling solution would be:

input.invalid {
  border-style: solid;
  border-color: red;
}

In addition, consider utilizing the invalid pseudo-element.

For further insights, it's recommended to explore the documentation regarding ASP.NET Core Blazor forms validation.

Answer №2

One way to implement this is by using the following code snippet:

      <AccordionItem class="@_accordianCss" Title="Accordion Item #1">
    private string _accordianCss => isValidationError ? "accordian-invalid" : "accordian-valid";

You can then include the styles in your global css or a separate css file.

If desired, you can also create functionality to expand/collapse the accordion without the need for JavaScript.

Update:

Below is a demonstration page that utilizes Bootstrap's built-in "invalid" CSS styling:

@page "/"
@using Microsoft.AspNetCore.Components.Forms
@using System.ComponentModel.DataAnnotations;

<div class="@_validationCss p-4 m-2">
    <EditForm EditContext="_editContext" OnSubmit="@OnSubmitHandler">
        <DataAnnotationsValidator />
        <div>
            <label class="form-label" >Enter name: </label>
            <InputText class="form-control" id="name" @bind-Value="_customer.Name" /><br />
            <ValidationMessage For="@(() => _customer.Name)" />
        </div>
        <div class="text-end mb-2">
            <button class="btn btn-primary" type="submit">submit</button>
        </div>

    </EditForm>
</div>

<div class="alert @(_validated ? "alert-success" : "alert-danger")">
    <p>Model valid: @_validated.ToString()</p>
</div>

@code {
    private EditContext? _editContext;
    private Customer _customer = new();
    private bool _validated = true;
    private string _validationCss => _validated ? "modified valid" : "invalid";

    protected override void OnInitialized()
    {
        _customer = new Customer();
        _editContext = new(_customer);
        _editContext.OnValidationStateChanged += this.OnValidationStateChanged;
    }

    private void OnValidationStateChanged( object? sender, ValidationStateChangedEventArgs e )
    {
        if (_editContext is not null)
            _validated = _editContext.GetValidationMessages().Count() == 0;

        // This is an event so there's no built-in call to StateHasChanged
        this.StateHasChanged();   
    }

    private void OnSubmitHandler()
    {
        _validated = _editContext?.Validate() ?? false;
    }

    public class Customer
    {
        [Required] public string? Name { get; set; }
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discover how ReactJS can dynamically display or hide div elements based on specific conditions being met within JSON data

How do I show or hide a div based on a condition in React, using data from a JSON array? I have implemented the code below, but changing the value of isPassed={resultPass.pass} to isPassed={resultPass.failed} still displays the result as pass. I came acro ...

Quantities with decimal points and units can be either negative or positive

I need a specialized input field that only accepts negative or positive values with decimals, followed by predefined units stored in an array. Examples of accepted values include: var inputValue = "150px"; <---- This could be anything (from the input) ...

The NextJS application briefly displays a restricted route component

I need to ensure that all routes containing 'dashboard' in the URL are protected globally. Currently, when I enter '/dashboard', the components display for about a second before redirecting to /login Is there a way to redirect users to ...

Creating chained fetch API calls with dependencies in Next.js

I am a novice who is delving into the world of API calls. My goal is to utilize a bible api to retrieve all books, followed by making another call to the same api with a specific book number in order to fetch all chapters for that particular book. After ...

Issue with saving new entity in Entity Framework 5 when creating a 0..1 to Many Relationship

Currently, I am utilizing ASP.NET MVC 4 in conjunction with Entity Framework 5 for my application. The database was generated using the model-first approach. In this setup, there are two main tables: a running log table and a shoes table. A running log ent ...

What is the easiest way to simulate the Ctrl+C key event using jQuery?

I need to programmatically simulate pressing Ctrl+C in order to copy text from a page. My initial attempt looked like this: $('#codetext').click( function() { $("#codetext").trigger({ type: 'keydown', which: 99 }); } Her ...

Error: req.body or req.params.id is not defined in the current context (PUT and PATCH requests)

I'm experiencing an issue where both req.body and req.params.id are returning undefined even though I am using express.json() before the app.patch. I have tried changing the route to /:id, but that did not resolve the problem. Interestingly, it works ...

Steps to isolate the "changed" values from two JSON objects

Here is a unique question that involves comparing JSON structures and extracting the differences. A JqTree has been created, where when the user changes its tree structure, both the "old" JSON and "new" JSON structures need to be compared. Only the values ...

Issue with React nodemailer: net.isIP() is not a valid function

I'm currently working on a contact page in React and facing difficulties with the email functionality. My attempt involves using nodemailer and here is the snippet of my code: var nodemailer = require('nodemailer'); var xoauth2=require(&ap ...

Connection timeout on Selenium WebDriver

I am facing an issue while running Selenium tests on my Teamcity build server. The tests are unable to start and I am getting the following error message: OpenQA.Selenium.WebDriverException : The HTTP request to the remote WebDriver server for URL http ...

unable to retrieve data using ajax

Having some trouble with my ajax code that is supposed to print values: success: function(returndata) { $('#first').html("<div id='first' class='progress-bar progress-bar-primary' role='progressbar' aria-valu ...

Tips for retrieving user input and displaying it on an HTML page

I have encountered an issue with displaying user input in a table. The code for the table display is as follows: <tr ng-repeat="user in users" ng-class-even="'bg-light-grey'" ng-if="isLoading==false"> <td> ...

Is it possible for Angular and Flux to collaborate harmoniously?

Flux is a unique unidirectional data flow concept developed by the React team, offering various benefits such as Undo/Redo functionality, ease of testing, maintaining a single app state, and more. Exploring the idea of integrating Flux with AngularJs could ...

Jquery selector failing to target correct <form> element within Shopify theme

I'm feeling a bit lost here! Trying to zero in on a form within my page and utilize jQuery's serializeArray() function to extract all the values from said form. <div class="page-width"> <header class="section-header ...

"When attempting to upload an image from the front end, the issue arises that req.file

I have been troubleshooting this issue by referring to similar posts, but I am still facing the problem of getting 'undefined' when using console.log. I have followed instructions for defining the multer middleware from other sources, so I am uns ...

unable to effectively test promises with stubs using nodejs mocha

Currently, I am facing a couple of challenges when attempting to perform unit testing on promises using Mocha. 1) The main issue I encounter is an Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Prom ...

Securing client side routes in Vue.js: Best practices

Currently, I am in the process of developing a spa using Vue.js as the front end framework. It interacts with a back-end system that utilizes pure JSON and jsonwebtokens for security. While I am more experienced with the React ecosystem, my new role requir ...

Learn the position of a div element that appears following the lazy loading of images

I am struggling to make a div sticky below a set of lazy load images. The issue lies in the fact that the offset of the div keeps changing due to the lazy loading images pushing it down. There are 4 images with unknown heights, making it difficult to acc ...

Ensure the beginning and ending times are accurate for newly added input fields using jQuery

I've included a JSFIDDLE link here for reference. The validation for start and end time kicks in when the 'Next' button is clicked, located on the same page. I'm looking to validate the start and end times for dynamically generated fiel ...

Adding a foreign key reference in entity framework 3.5 is crucial for establishing proper relationships between entities

I currently have 3 tables: a. Employee (EmpID (primary key), EmpName) b. Department (DepID (primary key), DepName) c. EmployeeDepartmentMapping (ID (primary key), EmpID(foreign key), DepID(foreign key)) As I try to add a new employee, my goal is to als ...