4

I have a Blazor site, I am using an HTML template that has CSS and JS for styling.

I have imported the assets into the wwwroot, and I have made a reference to them in the _Host.cshtml file; The styling and certain elements seem to be working... However I've noticed the animations and other portions of the javascript are not working as intended...

For example, I have an accordion, and it doesn't expand or close.

I made the same page in an HTML format and put that in the wwwroot... When I run the code and navigate to that page, it seems to be working just fine. But on my razor page, it is not...

This is it on the .razor component

accordion does not expand on .razor

This is it on the .html file I made in the wwwroot

accordion works on .html Here is the code...

_Host.cshtml

<!DOCTYPE html>
<html lang="en">
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="Template Mo">
    <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">

    <title>Online Quoting Tool</title>

    <link rel="stylesheet" type="text/css" href="~/assets/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="~/assets/css/font-awesome.css">
    <link rel="stylesheet" type="text/css" href="~/assets/css/style.css">
    <link rel="stylesheet" type="text/css" href="~/assets/css/owl-carousel.css">

</head>
<body>
    <!-- ***** Preloader Start ***** -->
    <div id="preloader">
        <div class="jumper">
            <div></div>
            <div></div>
            <div></div>
        </div>
    </div>
    <!-- ***** Preloader End ***** -->
    <component type="typeof(App)" render-mode="ServerPrerendered" />

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>



    <!-- ***** Footer Start ***** -->

    <!-- jQuery -->
    <script type="text/javascript" src="~/assets/js/jquery-2.1.0.min.js"></script>

    <!-- Bootstrap -->
    <script type="text/javascript" src="~/assets/js/popper.js"></script>
    <script type="text/javascript" src="~/assets/js/bootstrap.min.js"></script>

    <!-- Plugins -->
    <script type="text/javascript" src="~/assets/js/owl-carousel.js"></script>
    <script type="text/javascript" src="~/assets/js/scrollreveal.min.js"></script>
    <script type="text/javascript" src="~/assets/js/waypoints.min.js"></script>
    <script type="text/javascript" src="~/assets/js/jquery.counterup.min.js"></script>
    <script type="text/javascript" src="~/assets/js/imgfix.min.js"></script>

    <!-- Global Init -->
    <script type="text/javascript" src="~/assets/js/custom.js"></script>
    <script src="_framework/blazor.server.js"></script>
</body>

custom.js (accordion functions)

 const Accordion = {
    settings: {
      // Expand the first item by default
      first_expanded: false,
      // Allow items to be toggled independently
      toggle: false
    },

    openAccordion: function(toggle, content) {
      if (content.children.length) {
        toggle.classList.add("is-open");
        let final_height = Math.floor(content.children[0].offsetHeight);
        content.style.height = final_height + "px";
      }
    },

    closeAccordion: function(toggle, content) {
      toggle.classList.remove("is-open");
      content.style.height = 0;
    },

    init: function(el) {
      const _this = this;

      // Override default settings with classes
      let is_first_expanded = _this.settings.first_expanded;
      if (el.classList.contains("is-first-expanded")) is_first_expanded = true;
      let is_toggle = _this.settings.toggle;
      if (el.classList.contains("is-toggle")) is_toggle = true;

      // Loop through the accordion's sections and set up the click behavior
      const sections = el.getElementsByClassName("accordion");
      const all_toggles = el.getElementsByClassName("accordion-head");
      const all_contents = el.getElementsByClassName("accordion-body");
      for (let i = 0; i < sections.length; i++) {
        const section = sections[i];
        const toggle = all_toggles[i];
        const content = all_contents[i];

        // Click behavior
        toggle.addEventListener("click", function(e) {
          if (!is_toggle) {
            // Hide all content areas first
            for (let a = 0; a < all_contents.length; a++) {
              _this.closeAccordion(all_toggles[a], all_contents[a]);
            }

            // Expand the clicked item
            _this.openAccordion(toggle, content);
          } else {
            // Toggle the clicked item
            if (toggle.classList.contains("is-open")) {
              _this.closeAccordion(toggle, content);
            } else {
              _this.openAccordion(toggle, content);
            }
          }
        });

        // Expand the first item
        if (i === 0 && is_first_expanded) {
          _this.openAccordion(toggle, content);
        }
      }
    }
  };

  (function() {
    // Initiate all instances on the page
    const accordions = document.getElementsByClassName("accordions");
    for (let i = 0; i < accordions.length; i++) {
      Accordion.init(accordions[i]);
    }
  })();

1 Answer 1

4

Good afternoon,

From my experience calling Javascript in a Blazor Component requires use of the IJS runtime. Here is the Microsoft Blazor Documentation for this issue:

https://learn.microsoft.com/en-us/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-5.0

Essentially you use the IJS runtime to call specific methods from your custom JS documents.

Sign up to request clarification or add additional context in comments.

3 Comments

So forgive me, because I'm new to blazor... The nav bar seems to be working with the JS files, so i would need to call the accordion functions on the actual accordion? It wouldn't read from the JS file like it does on the HTML page I created?
I am unable to answer this question for sure, but I have always had to inject IJS runtime to get the functions to work properly with anything rendered by my components. I would guess this is due to how the components are rendered in the @Body tag in the MainLayout.razor file. I assume your NavBar is rendered in a separate section of the layout.
@Arkayik if the HTML file was in the wwwroot folder, it's able to find the imports you've included in your _Host.cshtml (which has since been replaced in Blazor to be the App.razor). To use JsInterOp inside of a blazor component, you need to inject IJSRuntime like mentioned abobve, and you may also need to call the corresponding JavaScript function in the methods you've set up in the Accordion.razor component. For example, if you have a <button @onclick="@OnClickMethod"> inside of your OnClickMethod you could call await JsRuntime.InvokeVoidAsync("NameOfJsFunction")

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.