Diego Unanue
Diego Unanue

Reputation: 6836

Variable Scope in javascript in MVC

I've got the following script:

$('#select').change(function () {
    var selectedIndex = $('#select').val();
    $('#priceTxt').val(@Model.ListProducts[selectedIndex].Price);
});

The issue is that the selectedIndex variable inside $('#priceTxt').val(@Model.ListProducts[selectedIndex].Price); says 'cannot resolve symbol selectIndex' like out of scope.

Why that happens and how can I fix it? Regards

Upvotes: 1

Views: 1061

Answers (3)

Erik Noren
Erik Noren

Reputation: 4339

@Model.ListProducts[selectedIndex].Price executes on the server and the result is added to the HTML before it is sent out to the client. This means selectedIndex is out of scope because you don't define and use it until it's in the browser.

You can't mix Razor markup with JavaScript. Razor has already done its work long before JavaScript gets hold of it.

Most likely what you want is to use your model to generate your drop down using the price as the value field and the product as the label. You already have everything else wired up; just replace your use of @Model with JavaScript to get the selected option's value instead.

EDIT: An approach I use for an JavaScript people/entity picker is to serialize data I need either as a delimited string or a JSON stringified object and store that as an attribute on the element (or parent). This lets me have multiple instances of the control on the page and use a single jQuery selector and code block to "restore" or read from the data to grab whatever information I need for dynamic display.

For instance:

<div data-serialized-products="@Model.PriceList.ToDataString()">
  @Html.DropDownFor(m => ..., new { @class="showPrice"})
</div>

<script type="text/javascript">
  $(function() {
    $(".showPrice").change(function() {
      var $dd = $(this);
      //Grab the selected value, then do $dd.parent("div").data("serialized-products")
      //to and either string split (for string delimited) or use JSON parse and access
      //the property you need to put in the text box. Bonus - you can put your textbox
      //target id in another data- attribute so you can repeat this set of controls.
    });
  });
</script>

You would need to create your ToDataString() to either return a concatenated string or a JSON stringified string. Your JavaScript function would need a matching JSON parse or delimited string split to access the value. As long as your object isn't very big (and serialize only the property/properties you need) then this should be a useful approach.

Upvotes: 0

Abbas Galiyakotwala
Abbas Galiyakotwala

Reputation: 3019

Use var to store model value

$('#select').change(function () {
    var selectedIndex = $('#select').val();
    var price='@Model.ListProducts[selectedIndex].Price';
    $('#priceTxt').val(price);
});

Upvotes: 0

Matt Houser
Matt Houser

Reputation: 36073

You are mixing server-side and client-side code. The javascript code (the var selectedIndex part) will run on the client, but razor code (the @Model.ListProducts[selectedIndex].Price part) wants to run on the server.

You can download the product data "on-demand" as the user selects products:

$('#select').change(function () {
    var productId = $('#select').val();
    $.ajax({
      url: '@Url.Action("GetProduct")',
      data: { productId: productId },
      success: function(results) {
        $('#priceTxt').val(results.Price);
      }
    });
});

Upvotes: 1

Related Questions