0
<!--language: lang-html--> 
@foreach (var book in Model.Category.Books)
   {

      <div class="rate-star-@book.Id"></div>
        <script>
          $(".rate-star-@book.Id").stars({ stars:5, readonly:false});
        </script>

  }

A brief explanation about what I'm trying to do: This script code inside the loop is one of the star rating plugins that I need to implement for books on the page. The problem here is that I need to include jquery code further up in the body but since JQuery library loads later than the script code, I get "$ is not defined" error.

What Have I tried: I tried to implement the solution on this page
[Handling code which relies on jQuery before jQuery is loaded written by Ashkan Mobayen Khiabani. I put the code inside a function. The function is called at the bottom of the body. It is supposed to be called as many times as it's created in per iteration. But since it's called only once at the bottom the other created functions don't run and only one book gets affected by the function as a result.

 <!--language: lang-html--> 
    @foreach (var book in Model.Category.Books)
       {                  
          <div class="rate-star-@book.Id"></div>
            <script>
   function rateStar{
              $(".rate-star-@book.Id").stars({ stars:5, readonly:false});
            </script>
           }                                   
      }

@section scripts
 { 
     <script>
 rateStar(); 
     </script>
}

So how to do that function gets called as many times as it's created in the document?

Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
Cavid
  • 125
  • 13
  • It seems that you are including jQuery later than these script tags. So it's not a `foreach` issue but order of inclusions. – VLAZ Apr 07 '19 at 13:30
  • have a look at this question: [https://stackoverflow.com/questions/8298430/handling-code-which-relies-on-jquery-before-jquery-is-loaded](https://stackoverflow.com/questions/8298430/handling-code-which-relies-on-jquery-before-jquery-is-loaded/25636162#25636162) – Ashkan Mobayen Khiabani Apr 07 '19 at 13:33
  • @Ashkan Mobayen Khiabani I have edited the question considering your solution and described problem encountered after implementing it. Please take a look at it again. – Cavid Apr 08 '19 at 14:31
  • @Cavid as you have changed the question (that actually it was better to add a new question), I reopened the question and answered it. I hope it helps – Ashkan Mobayen Khiabani Apr 08 '19 at 15:17

1 Answers1

1

in Views/Shared open _Layout.cshtml and in the head tag create a script tag and create an array (lets name it postJquery:

<head>
...
   <script>var postJquery = [];</script>
...
</head>

Now in the same file (_Layout.cshtml) go to the bottom and add this code before ending of body tag:

<script>for(var i=0;i<postJquery.length;i++) postJquery[i]();</script> //just ad this line
</body>

Now anywhere that you need to run a code that depends on jquery just add it to a function and add it to postJquery array and it will run after jQuery is loaded like this:

postJquery.push(function(){
    //your code goes here
});

for example, your case would be:

@foreach (var book in Model.Category.Books)
   {                  
      <div class="rate-star-@book.Id"></div>
        <script>
          postJquery.push(function(){
              $(".rate-star-@book.Id").stars({ stars:5, readonly:false});
          });
        </script>
       }                                   
  }

The code above will run just fine, but there is what I don't like about it that the script tag and its content will be repeated for each book item, for example, if you have 20 books in your loop, the following code will be repeated 20 times (of course book id will change for each one):

<script>
     postJquery.push(function(){
          $(".rate-star-@book.Id").stars({ stars:5, readonly:false});
     });
</script>

So instead I would do something like this:

@foreach (var book in Model.Category.Books)
   {                  
      <div class="rate-star" data-id="@book.Id"></div>
   }                                   
<script>
   postJquery.push(function(){
       $(".rate-star").stars({ stars:5, readonly:false});
   });
</script>

As I don't know about .stars if it should be used on a single element (and clicking on above code effects all items) you could do it like this:

@foreach (var book in Model.Category.Books)
   {                  
      <div class="rate-star" data-id="@book.Id"></div>
   }                                   
<script>
   postJquery.push(function(){
       $(".rate-star").each(function(){
            $(this).stars({ stars:5, readonly:false});
       });
   });
</script>
Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171