简体   繁体   中英

Can I use Javascript (with @ syntax) from partial into the main view?

Apologies if I'm using the wrong terminology, I'm fairly new to this technology.

I have a view which we'll call MainView.cshtml:

<div>
  @RenderPartial("_Partial");
</div>

<script type="text/javascript">
 $(document).ready(function() {
    someFunctionDefinedIn_Partial();
 }
</script>

The _Partial view has javascript that defines a function (in this case someFunctionDefinedIn_Partial .

function someFunctionDefinedIn_Partial()
{
  // This uses the "@" syntax to access C# variables, which can be done in .cshtml
  alert("Hello. This variable is from C#: @ClassInCSharp.Variable");
}

When I run the code above I'm told in the chrome console that the function someFunctionDefinedIn_Partial doesn't exist. I'm guessing this is because javascript in a partial doesn't make its way out to the container.

I looked around a bit and found that I can extract the javascript to its own .js file and reference that as shown in this SO post: How to render JavaScript into MasterLayout section from partial view?

However, the post above suggests extracting javascript into its own separate file .js. If I do this, then I am using "raw" javascript, so I can't use the @ notation to reference variables from my C#.

Is it possible to somehow include javascript in my MainView.cshtml which also has access to the @ syntax so I can use C# methods/variables? If not, is it possible to create an external javascript file, but have it be a .cshtml file so I can use the "@" syntax?

Can I use Javascript (with @ syntax) from partial into the main view?

Yes, but the order of javascript operations is very important. Strictly speaking, the following javascript code should error out:

console.log(myvariable);
var myvariable = "hello world!";

I'm using a variable before it's defined. That is the similar problem you are having.

Would I recommend using Javascript directly inside a view?

Definitely almost exclusively never . The way most javascript/css/html is written today is tightly coupled enough. Adding a coupling to C# seems like a giant code smell . My personal preference is to add data to html elements and have the javascript only coupled to my html. So instead of :

<script>
var myIds = [@(string.Join(Model.People.Select(p => Id.ToString().ToArray(), ",")];
</script>

Which is just insanely ugly and hard to debug, I apply my values to the html presentation that is representing my object:

<div data-id="@model.Id" class="person">
  Person Name: @Html.DisplayFor(m => m.name)
</div>

<script>
var myIds = [];
$('.person').each((i,p) => myIds.push($(p).data("Id"));
</script>

Now I can't really make a mistake about making sure the Id's in my array are the same ones on the page, everything is encapsulated together.

The other code smell is using @() methods in a view for logic. For example, I see a lot of:

@foreach(var person in Model.persons) 
{
  if (person.Age >= 21)
  {
    <div>Adult</div>
  }
  else
  {
    <div>Child</div>
  }
}

To me, that is logic in a view. My definition of a ViewModel is a model that represents all the necessary data-points (even those derived from logic). So I would do something like:

public class PersonVM
{
  public DateTime BornOn { get; set; }
  public bool IsAdult { get { return /*BornOnLogic*/; } ]
}

So in my view, I don't understand why anyone would need to use any C# directly within Javascript.

I would also recommend reading Philip Walton's (Google Engineer) -Decoupling Your HTML, CSS, and JavaScript .

I don't recommend you to include JS in a Partial view, as it can be added many times in a given view. Take a look at link

I suggest you to move the partials JS to the main view.

UPDATE

If you don't have any other option, consider that Razor cannot be used in plain JS: Link

What you can do is to extract the C# values needed in your JS and send them when invoking the JS. So you could have:

function someFunctionDefinedIn_Partial(variableValue)
{
  // This uses the "@" syntax to access C# variables, which can be done in .cshtml
  alert("Hello. This variable is from C#: " + variableValue);
}

And invoke it from the partial view:

someFunctionDefinedIn_Partial(@ClassInCSharp.Variable);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM