This is a migrated thread and some comments may be shown as answers.

Limit ComboBox "Text Entered" to items in the drop down list except if a certain option is selected in the "Parent" ComboBox.

6 Answers 273 Views
ComboBox
This is a migrated thread and some comments may be shown as answers.
Agropur
Top achievements
Rank 1
Agropur asked on 26 Nov 2013, 02:59 PM
What I'm trying to do is I have 2 ComboBoxes that are setup in a Cascading relationship.  What I am not able to get working is that when 1 option is selected in the first ComboBox the cascaded ComboBox should ONLY allow choices from the Items list it is populated with.  When a 2nd option is selected in the first ComboBox(i.e. Other) the cascaded ComboBox should allow ANY text to be entered.

How can I achieve this?  Below is my View and Controller in question. 

VIEW:
<div class="form-group">
            @Html.LabelFor(model => model.locationCode, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @(Html.Kendo().ComboBox()
                        .Name("locationCode")
                        .Filter(FilterType.Contains)
                        .DataTextField("Text")
                        .DataValueField("Value")
                        .BindTo(Model.Locations)
                        .Suggest(true)
                )
                @Html.ValidationMessageFor(model => model.locationCode)
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.loadType, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @(Html.Kendo().ComboBox()
                        .Name("loadType")
                        .Filter(FilterType.Contains)
                        .DataTextField("Text")
                        .DataValueField("Value")
                        .BindTo(Model.LoadTypes)
                        .Suggest(true)
                )
                @Html.ValidationMessageFor(model => model.loadType)
            </div>
        </div>
 
        <div class="form-group">
            @Html.LabelFor(model => model.loadDescrip, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @(Html.Kendo().ComboBox()
                        .Name("loadDescription")
                        .Filter(FilterType.Contains)
                        .DataTextField("DocCode")
                        .DataValueField("DocCode")
                        .DataSource(source =>
                        {
                            source.Read(read =>
                            {
                                read.Action("GetCascadeDocumentNumbers", "DockDoor")
                                    .Data("filterLoadDescription");
                            })
                          .ServerFiltering(true);
                        })
                        .Enable(false)
                        .AutoBind(false)
                        .CascadeFrom("loadType")
                )
                <script>
                    function filterLoadDescription() {
                        return {
                            locCode: $("#locationCode").val(),
                            loadType: $("#loadType").val(),
                            docNumFilter: $("#loadDescription").data("kendoComboBox").input.val()
                        };
                    }
                </script>
                @Html.ValidationMessageFor(model => model.loadDescrip)
            </div>
        </div>
CONTROLLER:
public JsonResult GetCascadeDocumentNumbers(string locCode, string loadType, string docNumFilter)
{
    if (loadType != "OPEN" && loadType != "GENERIC")
    {
        var docNums = db.GetCurrentDocumentNumbers(locCode, loadType).AsEnumerable();
 
        if (!string.IsNullOrWhiteSpace(docNumFilter))
        {
            docNums = docNums.Where(x => x.Contains(docNumFilter));
        }
 
        return Json(docNums.Select(x => new { DocCode = x.ToString() }), JsonRequestBehavior.AllowGet);
    }
    return Json(string.Empty, JsonRequestBehavior.AllowGet);
}


6 Answers, 1 is accepted

Sort by
0
Agropur
Top achievements
Rank 1
answered on 27 Nov 2013, 08:29 PM
So here is what I have so far:

In my VIEW:
<div class="form-group">
           @Html.LabelFor(model => model.loadType, new { @class = "control-label col-md-2" })
           <div class="col-md-10">
               @(Html.Kendo().ComboBox()
                       .Name("loadType")
                       .Filter(FilterType.Contains)
                       .DataTextField("Text")
                       .DataValueField("Value")
                       .BindTo(Model.LoadTypes)
                       .Suggest(true)
               )
               @Html.ValidationMessageFor(model => model.loadType)
           </div>
       </div>
 
       <div class="form-group">
           @Html.LabelFor(model => model.loadDescrip, new { @class = "control-label col-md-2" })
           <div class="col-md-10">
               @(Html.Kendo().ComboBox()
                       .Name("loadDescrip")
                       .Filter(FilterType.Contains)
                       .DataTextField("DocCode")
                       .DataValueField("DocCode")
                       .DataSource(source =>
                       {
                           source.Read(read =>
                           {
                               read.Action("GetCascadeDocumentNumbers", "DockDoor")
                                   .Data("filterLoadDescription");
                           })
                         .ServerFiltering(true);
                       })
                       .Enable(false)
                       .AutoBind(false)
                       .CascadeFrom("loadType")
                       .Events(e =>
                           {
                   e.Change("onChange");
                           })
               )
               @Html.ValidationMessageFor(model => model.loadDescrip)
           </div>
       </div>

Also in my view, the Script stuff:
<script>
    function filterLoadDescription() {
        return {
            locCode: $("#locationCode").val(),
            loadType: $("#loadType").val(),
            docNumFilter: $("#loadDescrip").data("kendoComboBox").input.val()
        };
    };
 
    function onChange(e) {
        var lT = $("#loadType").data("kendoComboBox").input.val();
        if (lT != "Generic") {
            // Here I need to compare 'lD' to what is populated in the comboBox dropdown
            if (this.selectedIndex == -1) {
                this._filterSource({
                    value: "",
                    field: this.options.dataTextField,
                    operator: "contains"
                });
                var comboBox = $("loadDescrip").data("kendoComboBox");
                comboBox.select(1);               
            }           
        }
    };
</script>
The part that I cannot seem to make work is what's inside the if() statement.  What I am trying to accomplish is that, depending on what they select in a previous combobox this child combobox will not allow custom text.  This is where I am trying to check for that.

In fact, the line `comboBox.select(1)` generates a JavaScript runtime error: "Unable to get property 'select' of undefined or null reference"

0
Georgi Krustev
Telerik team
answered on 28 Nov 2013, 10:20 AM
Hello,

I will suggest you use the filter method of the data source:
var that = this;
 
if (that.selectedIndex == -1) {
    that.dataSource
          .one("change", function() {
               that.select(1);
          })
          .filter({
             value: "",
             field: that.options.dataTextField,
             operator: "contains"
          });
}
Note that data source is asynchronous and you will need to apply the required changes when the widget is re-bound. Also please avoid using private methods (with underscore) as they can change in future.

Regarding second issue, I am not exactly sure what is the cause of the problem. If it still persists then I will ask you to send us a simple repro test project. Thus I will be able to observe the issue locally and advice you further.

Regards,
Georgi Krustev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Agropur
Top achievements
Rank 1
answered on 02 Dec 2013, 04:43 PM
Thanks.  Couple of follow up questions:
What does ".one()" do?
Could you explain, a little, what you meant with this statement:"you will need to apply the required changes when the widget is re-bound."?  What more would I need to do besides what was shown in your answer?  I understand the Why just not the How...
Lastly, how do I get the filter to clear itself?  I have an issue where the last value still sits in there even if the parent combobox choice would make it invalid.  I tried the following but maybe I'm not using it in the right way?  
// This is the Parent Combobox Change Event. $lD is the child one.
function
onTypeChange(e) {
    if (this.value() == "OPEN") {
        var $lD = $("#loadDescrip").data("kendoComboBox");
        $lD.dataSource.filter([]);
        //$lD.value("");
        $lD.text("empty");
        $lD.dataSource.read();
    }
}
0
Georgi Krustev
Telerik team
answered on 04 Dec 2013, 12:09 PM
Hello again,

The "one" method is a short-hand to listen to event raise only once. It is same as:
var changeHandler = function() {
     //
 
     widget.unbind("change", changeHandler);
}
 
widget.bind("change", changeHandler);
This code snippet shows the same functionality using the bind method of the ObservableObject.

With "you will need to apply the required changes when the widget is re-bound" statement I wanted to mention that any changes like selecting item or setting value will need to be done after the widget is re-populated. Wiring the change event of the dropdownlist's data source is sufficiant to achieve the aforementioned requirement. 

The applied filter can be cleared either using your approach or passing empty object as an argument:
$lD.dataSource.filter([])
 
/// or
 
$lD.dataSource.filter({});


Regards,
Georgi Krustev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Agropur
Top achievements
Rank 1
answered on 04 Dec 2013, 08:21 PM
Thanks. The filter thing still does not work, unless I am simply doing it wrong or not understanding what the filter is.  I have submitted a Support Ticket with my project attached to it.
0
Georgi Krustev
Telerik team
answered on 09 Dec 2013, 08:12 AM
Hello,

I've answered you  in the support thread on the same matter. I will suggest you continue our conversation there in order to avoid any duplications.

Regards,
Georgi Krustev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Tags
ComboBox
Asked by
Agropur
Top achievements
Rank 1
Answers by
Agropur
Top achievements
Rank 1
Georgi Krustev
Telerik team
Share this question
or