MVC UIHint/Parital view with JQuery multiselect, d

2019-09-06 14:25发布

问题:

I've been using this tutorial to create a screen where a user can add additional input fields on a given screen

Instead of using all textboxes Iv'e created a UIHint/Partial view that'll render a multi-select JQuery widget (I'm using this component)

ViewModel for each row item

 public class Micros
    {
        [UIHint("JsonComboBox")]
        [AdditionalMetadata("id", "Lab_T_ID")]
        [AdditionalMetadata("description", "Description")]
        [AdditionalMetadata("action", "LabTestOptions")]
        [AdditionalMetadata("controller", "Micro")]
        [AdditionalMetadata("noneSelectedText", "Test")]
        [AdditionalMetadata("comboboxWidth", "200")] 
        [DisplayName("Test")]
        public Nullable<int> Lab_T_ID { get; set; }

        [UIHint("JsonComboBox")]
        [AdditionalMetadata("id", "Lab_SD_ID")]
        [AdditionalMetadata("description", "Description")]
        [AdditionalMetadata("action", "LabSampleDetailOptions")]
        [AdditionalMetadata("controller", "Micro")]
        [AdditionalMetadata("noneSelectedText", "Sample Details")]
        [AdditionalMetadata("comboboxWidth", "300")]
        [DisplayName("Sample Details")]
        public Nullable<int> Lab_SD_ID { get; set; }

        [DisplayName("Result")]
        public string Result { get; set; }
    }

Partial View/UIHint

@model int?
@{
    var values = ViewData.ModelMetadata.AdditionalValues;
}
<select id="@values["id"]" multiple="multiple" style="width:@values["comboboxWidth"]px" > </select>
<script type="text/javascript">

        $.getJSON('@Url.Action((string)values["action"], (string)values["controller"])', 
                     null,
                    function (j) {
                        var options = '';

                    for (var i = 0; i < j.length; i++) {
                        options += '<option value="' + j[i].@values["id"] + '">' + j[i].@values["description"] + '</option>';
                    }
                    $('#@values["id"]').html(options);
                    $('#@values["id"] option:first').attr('selected', 'selected');
        });


    setTimeout(function () {

     $("#@values["id"]").multiselect({
       multiple: false,
       header: "Select an option",
       noneSelectedText: '@values["noneSelectedText"]',
       selectedList: 1
    });

    }, 300);

</script>

The components render fine on the initial page load, but when add the items, they get added... but it seems that the javascript doesn't execute/get added..

Any ideas? Still debugging this issue, will post the fix as soon as I find it, but I'm hoping someone can point me in the right direction

Update

So far I've discovered that (We'll it looks like), the UIHint/Partials don't get rendered at all when the user clicks to add another item. (Otherwise the select will be populated with items, and the JQuery widget will be applied)

回答1:

I would recommend you to remove all javascript from your partial. Javascript shouldn't be mixed with markup. So your editor template should contain only markup:

@model int?
@{
    var values = ViewData.ModelMetadata.AdditionalValues;
}


<span>
    <select multiple="multiple" style="width:@values["comboboxWidth"]px" data-url="@Url.Action((string)values["action"], (string)values["controller"])" data-noneselectedtext="@values["noneSelectedText"]" data-value="@values["id"]" data-text="@values["description"]"></select>
</span>

and then in a separate javascript file you will have a function which will be used when the Add another... button is clicked as shown in Steven Sanderson's article:

$('#addItem').click(function() {
    $.ajax({
        url: this.href,
        cache: false,
        success: function(html) { 
            // Here's the place to attach any plugins to the given row:

            var select = $('select', html);
            $.getJSON(select.data('url'), function(options) {
                $.each(options, function() {
                    select.append(
                        $('<option/>', {
                            value: this[select.data('value')],
                            text: this[select.data('text')]
                        })
                    );
                });

                select.multiselect({
                    multiple: false,
                    header: 'Select an option',
                    noneSelectedText: select.data('noneselectedtext'),
                    selectedList: 1
                });

                $('#editorRows').append(select);

            });
        }
    });
    return false;
});