2

I'm using MVC3 with razor view. I'm giving the user a list of <li>s to select from:

        <ol id="selectable">
            @foreach (var ebat in Model.AvailableSizes)
            {
                <li class="ui-widget-content">@ebat.Item1 x @ebat.Item2</li>                    
            }
        </ol>

where Model.AvailableSizes is a List<Tuple<int,int>>. When the user selects one of them, I want to be able to find from jQuery which Tuple<int,int> the user wants to use.

By the way I am using jqueryui Selectable with these list.

I guess I can find the selected element with $(".ui-selected:first"), but how can I get the associated Model data, namely @ebat.Item1 and @ebat.Item2, so that I can send them to the server as parameters?

I'm quite suspicious about my initial approach here, I mean it shouldn't be this hard. So if you could show me the better way to use model, html and jquery together in this kind of situations, it would be fantastic. Thanks.

Halo
  • 1,524
  • 3
  • 24
  • 39
  • where is that Darin guy, he'd be perfect for this question – Halo Jun 17 '12 at 12:58
  • Ok, we got it down to setting the viewmodel's hidden field. Now, I can set the hidden input's value, but that doesn't reflect upon the viewmodel. The viewmodel's property, SelectedSizeId is still zero, while the value of the hidden input in the html file is correctly set. What am I missing here? – Halo Jun 17 '12 at 17:11

2 Answers2

1

You can add a hidden field for selected value and set its value on a select event.

@Html.HiddenFor(m => m.SelectedSize)

Although, Tuple<T1,T2> doesn't have a parameterless constructor so model binder can't create an instance. You can provide an integer ID for each size and read that when from the POST request.

You should use Tuple<int,T1,T2> for your AvailableSizes property. Also you have to save ID value as a custom attribute on li element so you can save it in the hidden field.

Still MVC will not be able to read AvailableSizes property on post request so you will have to exclude that property and read only SelectedSize property.

Here's how your model properties should look like:

public IEnumerable<Tuple<int,T1,T2>> AvailableSizes { get; set; }
public int SelectedSize { get; set; }

You should save Size ID as a custom attribute:

<ol id="selectable">
    @foreach (var ebat in Model.AvailableSizes)
    {
        <li class="ui-widget-content" data-size-id="@ebat.Item1">@ebat.Item2 x @ebat.Item3</li>                    
    }
</ol>

You should provide the JavaScript for select events that should read the data-size-id attribute and set it to SelectedSize hidden field.

Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • I'm setting the custom attribute, retrieving it in the script, but I cannot use it when reaching for the model. `var sizeId` is the id, and the .js code below it is `var en = '@Model.AvailableSizes.ElementAt(sizeId).Item2';`, but it gives a compile error and says that sizeId doesn't exist. – Halo Jun 17 '12 at 14:31
  • You have to set its value to the hidden field shown above. You won't be able to populate AvailableSizes property on post request. You just get the id value from hidden field that is binded to SelectedSize property. – Ufuk Hacıoğulları Jun 17 '12 at 14:35
  • but if I can't get it, how am I going to set it? I'm this close, if I could just use that `sizeId` to query `AvailableSizes` – Halo Jun 17 '12 at 14:39
  • You have to populate the list just like in your GET method, then use the SelectedSize property you get from the hidden field. – Ufuk Hacıoğulları Jun 17 '12 at 14:43
  • Ok, I believe I will have to go to server twice with this way, am I right? – Halo Jun 17 '12 at 14:47
  • Nope, request will be on the server side when user submits the form. You will be just repopulating the size list upon that arrival. It's already inside your action method. – Ufuk Hacıoğulları Jun 17 '12 at 14:51
  • One last problem, I've been trying to set the hidden field's value from inside the script, but I don't think it's working. I use `$("#SelectedSizeId").val(sizeId);` to set the field, and right after that, I use var en = `'@Model.AvailableSizes.ElementAt(@Model.SelectedSizeId).Item2';` to retrieve it. SelectedSizeId always gives me 0, the default value. – Halo Jun 17 '12 at 15:34
  • @Halo You will get the value in the action method that handles the post request. You can't get it in your view. – Ufuk Hacıoğulları Jun 17 '12 at 20:26
0

Add attribute to li tag:

<li class="ui-widget-content" data="@ebat.Item1-@ebat.Item2">@ebat.Item1 x @ebat.Item2</li> 

Try the following jQuery Code:

    var value = $(".ui-selected:first").attr("data");
    var items = value.split("-");
    var item1 = items[0];
    var item2 = items[1];
Kapil Khandelwal
  • 15,958
  • 2
  • 45
  • 52
  • that could work probably, but it would kill the type orientation. I'm already not doing this really well, I can feel it. – Halo Jun 17 '12 at 13:43
  • Well, in the end, your way is the closest to what I'm going with now. I'm adding two custom attributes, and use them separately without split – Halo Jun 17 '12 at 18:19