PDA

View Full Version : [CLOSED] MultiCombox deselection not working properly



PriceRightHTML5team
Sep 25, 2014, 3:17 PM
Hi,

I have 2 MultiCombo's which is used to display Region & its Countries, if user selects one region from Region MultiCombo, its corresponding countries should get selected in Country MultiCombo and Vice Versa.

The issue i am facing is after selecting of 2 regions if user deselect first region its corresponding countries are getting deselected but if user deselect second region then its corresponding countries are not getting deselected.

I mean on second deselection of Region MultiCombo, countries not getting deselected.

Below is the sample code:

//Model




public class Country
{
public int COUNTRY_CD { get; set; }
public string COUNTRY_DESC { get; set; }
public int REGION1_CD { get; set; }
public int REGION2_CD { get; set; }
}

public class Region
{
public int REGION_CD { get; set; }
public string REGION_DESC { get; set; }
}

public class ViewModel
{
public List<Region> RegionList { get; set; }
public List<Country> CountryList { get; set; }
}



//Controller




public ActionResult Index()
{
List<Country> countryList = new List<Country>();
Country countryObj = new Country();

for (int i = 0; i <= 5; i++)
{
countryObj = new Country();
countryObj.COUNTRY_CD = i;
countryObj.COUNTRY_DESC = "Country-" + i;
if (i < 3)
{
countryObj.REGION1_CD = 100;
countryObj.REGION2_CD = 100;
}
else
{
countryObj.REGION1_CD = 200;
countryObj.REGION2_CD = 200;
}
countryList.Add(countryObj);
}

List<Region> regionList = new List<Region>();
Region regionObj = new Region();
regionObj.REGION_CD = 100;
regionObj.REGION_DESC = "Region-1";
regionList.Add(regionObj);

regionObj = new Region();
regionObj.REGION_CD = 200;
regionObj.REGION_DESC = "Region-2";
regionList.Add(regionObj);

ViewModel model = new ViewModel();
model.CountryList = countryList;
model.RegionList = regionList;

return View(model);
}



// View




@model TestProject.Controllers.MultiComboController.ViewM odel

@using System.Web.Optimization;
@{
ViewBag.Title = "Home Page";
var X = Html.X();
Layout = null;
}

@(Html.X().ResourceManager(ViewBag.ManagerConfig as MvcResourceManagerConfig))

<script>

//#region Function to make dropdown text as 'Multiselection' if two scenarios are seleected
var myGetDisplayValue = function () {
var value;
if (this.valueModels.length > 1) {
value = "Multi-selection";
} else {
value = this.displayTpl.apply(this.displayTplData);
}

return this.wrapBySquareBrackets ? "[" + value + "]" : value;
};

//On Region selection select corresponding countries
var RegionSelected = function (multiCombo, records) {

var regionList = App.CmbRegion.getValue();
var selectedCountries = App.CmbCountries.getValue();
var cntryStore = App.CmbCountries.getStore();
var countryCDArr = new Array();

for (var i = 0; i < regionList.length; i++) {
Ext.each(cntryStore.data.items, function (item) {
if (item.data.REGION1_CD == parseInt(regionList[i]) || item.data.REGION2_CD == parseInt(regionList[i])) {
countryCDArr.push(item.data.COUNTRY_CD);
}
});
}

var finalList = countryCDArr.concat(selectedCountries);
if (finalList.length > 1 && finalList.indexOf(-2) > -1) {
var item = App.CmbCountries.getStore().findRecord("COUNTRY_CD", -2)
App.CmbCountries.deselectItem(item);
finalList = $.grep(finalList, function (item) { return item !== -2 });
}
App.CmbCountries.setValue(finalList);
};

//On Region deselection deselect Corresponding countries
function RegionDeselected(record) {

var cntryStore = App.CmbCountries.getStore();
var countryCDArr = new Array();

Ext.each(cntryStore.data.items, function (item) {
if (item.data.REGION1_CD == parseInt(record.data.REGION_CD) || item.data.REGION2_CD == parseInt(record.data.REGION_CD)) {
countryCDArr.push(item.data.COUNTRY_CD);
}
});

for (var i = 0; i < countryCDArr.length; i++) {
var coutryRecord = cntryStore.findRecord("COUNTRY_CD", parseInt(countryCDArr[i]));
App.CmbCountries.deselectItem(coutryRecord);
}
};

</script>

<h2>Multi Select</h2>

@(

Html.X().Container().ID("cntr").Items(


X.MultiCombo().ID("CmbRegion")
.DisplayField("REGION_DESC")
.ValueField("REGION_CD")
.QueryMode(DataLoadMode.Local)
.Store(
X.Store().ID("storeRegion")
.Model(X.Model().Fields(
new ModelField("REGION_DESC"),
new ModelField("REGION_CD"))
)
.DataSource(Model.RegionList)
)
.CustomConfig(x => { x.Add(new ConfigItem() { Name = "getDisplayValue", Value = "myGetDisplayValue", Mode = ParameterMode.Raw }); })
.ListConfig(Html.X().BoundList()
.Listeners(events =>
{
events.Deselect.Handler = @"if (!App.CmbRegion.ignoreSelectChange) {RegionDeselected(record);}";
})
)
.EmptyText("Select Region").FieldLabel("Region").LabelCls("fieldLabelTop")
.Listeners(ls => { ls.Select.Fn = "RegionSelected";}),

X.MultiCombo().ID("CmbCountries")
.DisplayField("COUNTRY_DESC")
.ValueField("COUNTRY_CD")
.QueryMode(DataLoadMode.Local)
.Store(
X.Store().ID("storeCountries")
.Model(X.Model().Fields(
new ModelField("COUNTRY_DESC"),
new ModelField("COUNTRY_CD"),
new ModelField("REGION1_CD"),
new ModelField("REGION2_CD"))
)
.DataSource(Model.CountryList)
)
.CustomConfig(x =>
{ x.Add(new ConfigItem() { Name = "getDisplayValue", Value = "myGetDisplayValue", Mode = ParameterMode.Raw }); })
.EmptyText("Select Countries").FieldLabel("Countries")

)
)



Thanks

Daniil
Sep 26, 2014, 9:37 AM
Hi @PriceRightHTML5team,

I've debugged a bit the RegionSelected method. It looks like that method doesn't do its job well.

Let's consider this piece of code:

var finalList = countryCDArr.concat(selectedCountries);
if (finalList.length > 1 && finalList.indexOf(-2) > -1) {
var item = App.CmbCountries.getStore().findRecord("COUNTRY_CD", -2)
App.CmbCountries.deselectItem(item);
finalList = $.grep(finalList, function (item) { return item !== -2 });
}
App.CmbCountries.setValue(finalList);

When the two regions are selected and one of them gets deselected, the finalList variable contains 9 items.

Then the "if" condition is false, because the finalList doesn't contain the "-2" item. So, the deselectItem method is not called.

Then the setValue call takes the finalList variable that still contains 9 items. Why 9 if there are just 6 countries? And, moreover, only 3 should be selected.

So, there is a logical error (or a few errors) in the RegionSelected method.

PriceRightHTML5team
Sep 26, 2014, 10:41 AM
Hi Daniil,

You mean to say that SelectedRegion will get call on both select and deselect of an item in MultiCombo? If so then that will create a problem

As per my logic separate methods are written for both the events Select & Deselect, if Item get selected then only SelectedRegion should get fire and in SelectedRegion we are just selecting the items and if there is "-2" item then we are deselecting only that item.

For simplicity lets ignore or comment the if block as we are just selecting the items on "Select" event as its name suggest "Select"

And for deselecting the items RegionDeselected is written, in that only items will get deselected.

So here my concern is i need separate events for selecting & deselecting the items, so how to get that as you have already given one work around for deselect event as below in the post which i had posted earlier for Multi Select box.


"if (!App.CmbRegion.ignoreSelectChange) {RegionDeselected(record);"



Thanks

Daniil
Sep 26, 2014, 1:04 PM
Yes, it is how a MultiCombo works. If you deselect an item, it reselects all the rest items firing the Select event. Agree, it is controversial. Though, it might be very problematic to change that behavior.

So, instead of two events - Select and Deselect - I recommend to use the only Change event.

PriceRightHTML5team
Sep 26, 2014, 2:47 PM
Thanks Daniil for the reply.

As you told to use "Change" event of MultiCombo, is there any way to check on "Change" event whether item is selected or deselected? If so then it will be every helpful.

Daniil
Sep 26, 2014, 3:14 PM
You can compare the "oldValue" and "newValue". It is the parameters passed to a Change listener.