jQuery UI Widgets Forums Grid dropdownlist in Grid created via ASP NET MVC tag helper

This topic contains 9 replies, has 2 voices, and was last updated by  Hristo 7 years ago.

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author

  • Derek Broughton
    Participant

    I’ve been following http://www.jqwidgets.com/jquery-widgets-demo/demos/jqxgrid/#demos/jqxgrid/gridkeyvaluescolumnwitharray.htm, trying to get a working dropdownlist in a grid column.

    The following code appears to set the datafields and columns values to correctly match the demo, but while editing the “Type” column works, and sets EventCode correctly, the dropdown never has a default set to the current value, and unless in editing mode, the column is always blank.

    Do I need to override the cellsrenderer, too?

    @model uk.ac.sahfos.cpr.console.web.ViewModels.TowViewModel
    @using jQWidgets.AspNetCore.Mvc.TagHelpers;
    
    @{
        var towEvent = Model.Tow.DataEntryEvent.FirstOrDefault();
    }
    <div class="col-md-2">
         <jqx-grid alt-rows="true"
                  editable="true"
                  source-id-for="@(towEvent.EventId)"
                  selection-mode="singlerow"
                  theme="bootstrap"
                  edit="@Url.Action("Edit", "TowEvent")"
                  auto-height="true"
                  source="Model.Tow.DataEntryEvent"
                  id="jqxgrid">
            <jqx-grid-columns>
                <jqx-grid-column datafield-for="@(towEvent.EventCode)"></jqx-grid-column>
                <jqx-grid-column datafield="Event_Type"
                                     display-field="Event_Type"
                                     column-type="dropdownlist"
                                     text="Type"></jqx-grid-column>
                <jqx-grid-column datafield-for="@(towEvent.Comments)"></jqx-grid-column>
            </jqx-grid-columns>
        </jqx-grid>
    	<select id="EventCodes" style="display:none" class="">
    		<option value="1" selected="selected">Shoot</option>
    		<option value="4">Mid course haul</option>
    		<option value="5">Altered course</option>
    		<option value="6">Mid course shoot</option>
    		<option value="9">Haul</option>
    	</select>
    </div>
    
    @section Scripts {
        <script src="~/lib/jqwidgets/jqwidgets/jqxcore.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxbuttons.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxcalendar.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/globalization/globalize.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxdatetimeinput.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxscrollbar.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxgrid.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxgrid.columnsresize.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxgrid.edit.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxdata.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxgrid.selection.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxnumberinput.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxmenu.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxlistbox.js"></script>
        <script src="~/lib/jqwidgets/jqwidgets/jqxdropdownlist.js"></script>
        <script type="text/javascript">
            jQuery(function ($) {
                var grid = $("#jqxgrid");
                var adapter = grid.jqxGrid('source');
                // fix the dropdownlist 
                var eventCodes = $("#EventCodes").jqxDropDownList({ autoBind: true }).jqxDropDownList('source');
    
    			// I can't figure out proper values for datafield/display-field in the <jqx-grid-column> tag
    			// and, afaict, I still need to set "values" here
                var fields = adapter._source.datafields;
                for (var ix = 0; ix < fields.length; ix++) {
                    if (fields[ix].name == 'EventCode') {
                        fields[ix].name = 'Event_Type';
                        fields[ix].type = '';
                        fields[ix].value = 'EventCode';
                        fields[ix].values = { source: eventCodes, value: 'value', name: 'label' };
                        break;
                    }
                }
                fields = grid.jqxGrid('columns').records;
                for (var ix = 0; ix < fields.length; ix++) {
                    if (fields[ix].displayfield == 'Event_Type') {
                        fields[ix].createeditor = function (row, value, editor) {
                            editor.jqxDropDownList({ source: eventCodes, displayMember: 'label', valueMember: 'value' });
                        };
                        break;
                    }
                }
            });
        </script>
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    Derek Broughton
    Participant

    Adding

                                 init-editor="function(row_ix, value, editor){
                                    value = $('#jqxgrid').jqxGrid('source').records[row_ix].EventCode;
                                    editor.jqxDropDownList('selectItem',value);
                                 }"

    to the column definition fixes the initialization of the dropdownlist (the problem seems to be that value is always null when the editor is initialized).

    Adding

                                 cells-renderer="function (row_ix, columnfield, value, defaulthtml, columnproperties, row){ 
                                    value = row.EventCode;
                                    var codes = $('select#EventCodes,select#EventCodes_jqxDropDownList');
                                    codes.val(value)
                                    var retval = codes.find(':selected').text();
                                    return $(defaulthtml).text(retval)[0].outerHTML;
                                 }"

    fixes the cell rendering, though it’s awfully circuitous, and I needed two different selectors because the renderer gets called both before and after the jqxdropdownlist gets built on the select list!


    Hristo
    Participant

    Hello Derek Broughton,

    The “cells-renderer” callback is used to change the style of cells of one column otherwise if you want to change the style (appearing) when editing a concrete cell you should use “create-editor” and “init-editor” callbacks.
    Could you tell what you try to achieve and I will try to provide you a solution?

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com


    Derek Broughton
    Participant

    Sorry, I never saw this response because your forums make no attempt to inform a user when there’s a response to their posts… and I had a workable, though complicated, solution.

    What I’m trying to do is to make the “EventCode” column use a dropdown list, populated from the contents of the <select id="EventCodes"> tag, which was itself populated from the Model (so I’m always open to a simpler way to use it, too):
    <select id="EventCodes" style="display:none" class="form-control" asp-items="Model.Events"></select>

    I still see no solution that doesn’t involve the cells-renderer callback. If I omit the create-editor, init-editor, and cells-renderer callbacks, the grid initially displays with the cell showing the display value of the EventCode, but it’s not an editable dropdown. If I omit cells-renderer it’s a dropdown, but the default value is never set.


    Hristo
    Participant

    Hello Derek Broughton,

    I would like to suggest you if you want to try to use @section scripts and there you could use create-editor and init-editor.
    You could use this demos below where is presented how to implement cells-renderer, you could try to use the same approach for the “create-” and “init-editor”:
    https://aspcore.jqwidgets.com/mvc/TagHelpers/GridCellsRendering/light

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com


    Derek Broughton
    Participant

    As you can see, I already have create-editor in the script. As I have it currently implemented, I have the init-editor and cells-renderer defined using the tag helper. The problem is that I can’t find a way to create a working drop-down list entirely using the tag helper, or even one that has the column defined correctly, so I have to do some really ugly hacking in the script. It’s not as ugly as the script above, but it still can’t be right. And you said I shouldn’t need cells-renderer, so how do I get around it?

    <div class="container">
        <form asp-action="Edit">
            @{
                var towEvent = Model.Tow.DataEntryEvent.FirstOrDefault();
                if (towEvent == null)
                {
                    towEvent = new uk.ac.sahfos.cpr.console.web.Models.DataEntryEvent();
                }
            }
            <div class="row">
                <div class="col-md-12">
                    <jqx-grid alt-rows="true"
                              editable="true"
                              source-id-for="@(towEvent.EventId)"
                              selection-mode="singlerow"
                              theme="bootstrap"
                              edit="@Url.Action("Edit", "TowEvent")"
                              auto-height="true"
                              show-status-bar="true"
                              source="Model.Tow.DataEntryEvent"
                              id="jqxgrid">
                        <jqx-grid-columns>
                            <jqx-grid-column datafield-for="@(towEvent.EventDate)"
                                             column-type="datetimeinput"
                                             width="150"
                                             create-editor="function(row, cellvalue, editor){editor.jqxDateTimeInput({showTimeButton: true});}"
                                             cells-format="yyyy-MM-dd HH:mm" text="Date / Time"></jqx-grid-column>
                            <jqx-grid-column datafield-for="@(towEvent.EventCode)"
                                             display-field="Event_Type"
                                             column-type="dropdownlist"
                                             init-editor="function(row_ix, value, editor){
                                               // value is ALWAYS blank coming in...
                                               value = adapter.records[row_ix].EventCode;
                                               editor.jqxDropDownList('selectItem',value);
                                             }"
                                             cells-renderer="function (row_ix, columnfield, value, defaulthtml, columnproperties, row){
                                               value = row.EventCode;
    
                                               var codes = $('select#EventCodes,select#EventCodes_jqxDropDownList');
                                               codes.val(value)
                                               var retval = codes.find(':selected').text();
                                               return $(defaulthtml).text(retval)[0].outerHTML;
                                             }"
                                             text="Type"></jqx-grid-column>
                            <jqx-grid-column datafield-for="@(towEvent.Comments)"></jqx-grid-column>
                        </jqx-grid-columns>
                    </jqx-grid>
                    <select id="EventCodes" style="display:none" class="form-control" asp-items="Model.Events"></select>
                </div>
    @section Scripts {
    <script>
    jQuery(function ($) {
        // fix the dropdownlist 
        var eventCodes = $("#EventCodes").jqxDropDownList({ autoBind: true }).jqxDropDownList('source');
        var fields = adapter._source.datafields;
        var evtcode = fields.find(function (e) { return e.name == 'EventCode' });
        evtcode.name = 'Event_Type';
        evtcode.type = '';
        evtcode.value = 'EventCode';
        evtcode.values = { source: eventCodes, value: 'value', name: 'label' };
        var evttype = grid.jqxGrid('getcolumn', 'EventCode');
        evttype.datafield = 'EventCode';
        evttype.createeditor = function (row, value, editor) {
            editor.jqxdropdownlist({ source: eventCodes, displaymember: 'label', valuemember: 'value' });
        };
    }
    </script>
    }

    Hristo
    Participant

    Hello Derek Broughton,

    Could you check is there "jqxdropdownlist.js" and "jqxlistbox.js" references added.
    Also, Could you write me if there is some error message?

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com


    Derek Broughton
    Participant

    jqxlistbox and jqxdropdownlist are the last two scripts referenced in the code I originally posted. There are no error messages.

    I have a working dropdownlist, I’m just trying to find a way to actually do this with the tag helper, and not use the cellsrenderer callback that you say I don’t need.

    Now, it’s possible that the real issue is that I can’t manage to define my eventCodes
    <select id="EventCodes" style="display:none" class="form-control" asp-items="Model.Events"></select>
    –which I use to create the jqxDropDownList instance–before the jqxGrid. The moment I place that tag before the <jqx-grid> tag, the grid’s source adapter gets created with a missing field value (var source = { id: 'EventId', dataFields: [ { name: 'EventId', ...}], dataType: 'array', localData: [{ 'EventId': ... 'Tow': '', 'EventType': }, { 'EventId': ...) [Note, there’s no value for EventType; Tow and EventType are object references in the model. I have no use for them here, but getting them out of the model would be more trouble than it’s worth. It’s a bug in the tag helper, because it should always provide some value for each field].

    I should try hard-coding my EventCodes array, so that it has no relationship to the model, and defining it before the grid.


    Derek Broughton
    Participant

    If I hard-code the select list, I can put it before the <jqx-grid>, but it really doesn’t help as there doesn’t seem to be a way to get the jqxDropDownList defined before the grid is instantiated, which seems to be why I must have both the init-editor and cells-renderer callbacks defined.

    What I think I really need is some callback that’s invoked before rendering begins on the grid, and I don’t see such an option.


    Hristo
    Participant

    Hello Derek Broughton,

    I try to create one simple example with only create-editor callback.
    Please, take a look at this example:

    <script src="~/jqwidgets/jqxbuttons.js"></script>
    <script src="~/jqwidgets/jqxscrollbar.js"></script>
    <script src="~/jqwidgets/jqxgrid.js"></script>
    <script src="~/jqwidgets/jqxgrid.edit.js"></script>
    <script src="~/jqwidgets/jqxgrid.columnsresize.js"></script>
    <script src="~/jqwidgets/jqxgrid.filter.js"></script>
    <script src="~/jqwidgets/jqxgrid.selection.js"></script>
    <script src="~/jqwidgets/jqxgrid.sort.js"></script>
    <script src="~/jqwidgets/jqxgrid.pager.js"></script>
    <script src="~/jqwidgets/jqxgrid.aggregates.js"></script>
    <script src="~/jqwidgets/jqxgrid.grouping.js"></script>
    <script src="~/jqwidgets/jqxmenu.js"></script>
    <script src="~/jqwidgets/jqxlistbox.js"></script>
    <script src="~/jqwidgets/jqxdropdownlist.js"></script>
    
    @model IEnumerable<jQWidgets.AspNet.Core.Models.Employee>
    
    @{
        ViewData["Title"] = "ASP .NET MVC Testing Grid Example";
    }
    
    <jqx-grid theme="@ViewData["Theme"]" editable="true" sortable="true" filterable="true" width="400" auto-height="true" source="Model" instance="getInstance()">
        <jqx-grid-columns>
            <jqx-grid-column datafield="Events" editable="false" text="Events Group"></jqx-grid-column>
            <jqx-grid-column datafield="Type" width="250" column-type="dropdownlist" create-editor="createeditor()"></jqx-grid-column>
        </jqx-grid-columns>
    </jqx-grid>
    
    <select id="EventCodes" class="">
        <option value="1" selected="selected">Shoot</option>
        <option value="4">Mid course haul</option>
        <option value="5">Altered course</option>
        <option value="6">Mid course shoot</option>
        <option value="9">Haul</option>
    </select>
    
    @section scripts {
        <script type="text/javascript">
            function createeditor(row, cellvalue, editor, celltext, cellwidth, cellheight) {
                var eventsCodes = $('#EventCodes option');
                
                var allEventsCodes = [];
                for (var i = 0; i < eventsCodes.length; i++) {
                    var event = eventsCodes[i];
                    var label = event.label;
                    var value = event.value;
                    allEventsCodes.push({ label: label, value: value });
                }
                
                editor.jqxDropDownList({ source: allEventsCodes, displayMember: label, valueMember: value });
    
                editor.on('select', function (event) {
                    var args = event.args;
                    if (args) {
                        // index represents the item's index.                
                        var index = args.index;
                        var item = args.item;
                        // get item's label and value.
                        var label = item.label;
                        var value = item.value;
                        var type = args.type; // keyboard, mouse or null depending on how the item was selected.
                        $('#EventCodes').val(value);
                    }
                });
            }
            
            function getInstance(instance) {
                var initialType = $('#EventCodes option:selected').text();
                instance["addrow"](1, { Events: 'New Events', Type: initialType });
            };
        </script>
    }

    I hope this will help.

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com

Viewing 10 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic.