Select2 can't change value - javascript

I am dynamically loading a Select2 input with Ajax. Everything works fine, however, when I try to select a different value, It won't change for some reason. Here's an example of my problem: https://gyazo.com/f9ad7c3ead5fcd1d62740cc44f8d9691
As you can see, the value doesn't change when I click on it. Why does this happen? Maybe it helps when I say that both the first value and the other value have an ID of 1 (its data from different tables in the database) but different texts... How can I make it work?
$('.partnersupplierselect').select2({
ajax: {
dataType: "json",
type: "POST",
data: function (params) {
var group = $(this).parent().parent();
var choice = group.find('.partnersupplier:radio:checked').val();
return {
term: params.term,
'_token': token,
'choice': choice
};
},
url: '{{asset('logs/create/bmi/getpartnerssuppliers')}}',
cache: true,
processResults: function (data) {
return {
results: data
};
}
},
"language": {
"noResults": function () {
return "Geen partners / leveranciers gevonden.";
}
},
escapeMarkup: function (markup) {
return markup;
}
});
$('.partnersupplier').on('change', function(){
var group = $(this).parent().parent();
group.find('.partnersupplierselect').select2('val', '');
group.find('.partnersupplierselect').select2('data', null);
});
Here's the HTML, but that shouldn't be the problem. But in case someone wants to see it:
<div class="group">
<label class="mdl-radio mdl-js-radio mdl-js-ripple-effect" for="partner">
{{Form::radio('partnersupplier', 'partner', true, array('class' => 'mdl-radio__button partnersupplier', 'id' => 'partner'))}}
<span class="mdl-radio__label">Test1 </span>
</label>
<label class="mdl-radio mdl-js-radio mdl-js-ripple-effect margin-radio" for="supplier">
{{Form::radio('partnersupplier', 'supplier', false, array('class' => 'mdl-radio__button partnersupplier', 'id' => 'supplier'))}}
<span class="mdl-radio__label">Test2 </span>
</label>
<div class="form-group selectdiv" >
<label for="yearlypartnersuppliermaintainance">Blablabla<br></label>
<select id="yearlypartnersuppliermaintainance" name="yearlypartnersuppliermaintainance" class="searchselect searchselectstyle partnersupplierselect">
</select>
</div>
</div>

I figured it out!
I changed:
$('.partnersupplier').on('change', function(){
var group = $(this).parent().parent();
group.find('.partnersupplierselect').select2('val', '');
group.find('.partnersupplierselect').select2('data', null);
});
to:
$('.partnersupplier').on('change', function(){
var group = $(this).parent().parent();
group.find('.partnersupplierselect').empty().trigger('change');
});
For some reason, this works and the first thing doesn't. Weird, but at least I got it working!

Related

How to use select2 with multiple options using Razor and MVC

I am trying to create a multiple choice list using Select2, Razor and the MVC framework. My problem is that the object in the controller that receives the array input is always null. The front-end looks as follows:
<form class="form-horizontal" method="post" action="#Url.Action(MVC.Configurazione.Contatori.Edit())">
<div class="form-group">
<div class="col-lg-8">
<select class="form-control attributoSelect2" name="attributiSelezionati" value="#Model.AttributiSelezionati">
<option value="#Model.AttributiSelezionati" selected>#Model.AttributoDescrizione</option>
</select>
</div>
</div>
</form>
The action method "Edit", is the controller method that receives the array of chosen items from the drop-down list.
The Javascript is the following:
$('.attributoSelect2').select2({
placeholder: "Search attribute",
multiple: true,
allowClear: true,
minimumInputLength: 0,
ajax: {
dataType: 'json',
delay: 150,
url: "#Url.Action(MVC.Configurazione.Attributi.SearchAttrubutes())",
data: function (params) {
return {
search: params.term
};
},
processResults: function (data) {
return {
results: data.map(function (item) {
return {
id: item.Id,
text: item.Description
};
})
};
}
}
});
And finally the C# controller has an object that is expected to retrieve the data from the view and is defined:
public string[] AttributiSelezionati { get; set; }
and the HttpPost method that receives the data is:
[HttpPost]
public virtual ActionResult Edit(EditViewModel model) { }
Could someone give me some insight into what I am doing wrong and the areas that I should change in order to find the problem?
you class name error not attributoSelect2 is attributesSelect2 , I also make this mistake often. haha
<select class="form-control attributoSelect2" name="attributiSelezionati" value="#Model.AttributiSelezionati">
<option value="#Model.AttributiSelezionati" selected>#Model.AttributoDescrizione</option>
</select>
There are multiple reason for not being receiving data on server. First of all you need to change your select code as follow
#Html.DropDownList("attributiSelezionati", Model.AttributiSelezionati, new { #class = "form-control attributo select2" })
now go to console in browser and get the data of element to confirm that your code properly works in HTML & JS
After that you need to add attribute at your controller's action method as
[OverrideAuthorization]
[HttpPost]
You can try the following approach that has been used in some of our projects without any problem:
View:
#Html.DropDownListFor(m => m.StudentId, Enumerable.Empty<SelectListItem>(), "Select")
$(document).ready(function () {
var student = $("#StudentId");
//for Select2 Options: https://select2.github.io/options.html
student.select2({
language: "tr",//don't forget to add language script (select2/js/i18n/tr.js)
minimumInputLength: 0, //for listing all records > set 0
maximumInputLength: 20, //only allow terms up to 20 characters long
multiple: false,
placeholder: "Select",
allowClear: true,
tags: false, //prevent free text entry
width: "100%",
ajax: {
url: '/Grade/StudentLookup',
dataType: 'json',
delay: 250,
data: function (params) {
return {
query: params.term, //search term
page: params.page
};
},
processResults: function (data, page) {
var newData = [];
$.each(data, function (index, item) {
newData.push({
//id part present in data
id: item.Id,
//string to be displayed
text: item.Name + " " + item.Surname
});
});
return { results: newData };
},
cache: true
},
escapeMarkup: function (markup) { return markup; }
});
//You can simply listen to the select2:select event to get the selected item
student.on('select2:select', onSelect)
function onSelect(evt) {
console.log($(this).val());
}
//Event example for close event
student.on('select2:close', onClose)
function onClose(evt) {
console.log('Closed…');
}
});
Controller:
public ActionResult StudentLookup(string query)
{
var students = repository.Students.Select(m => new StudentViewModel
{
Id = m.Id,
Name = m.Name,
Surname = m.Surname
})
//if "query" is null, get all records
.Where(m => string.IsNullOrEmpty(query) || m.Name.StartsWith(query))
.OrderBy(m => m.Name);
return Json(students, JsonRequestBehavior.AllowGet);
}
Hope this helps...
Update:
Dropdown option groups:
<select>
<optgroup label="Group Name">
<option>Nested option</option>
</optgroup>
</select>
For more information have a look at https://select2.org/options.

Why kendo.observable do not read datasource

Could you explain why kendo ui observable do not read data source when bind to html ?
I based my code on this example : http://demos.telerik.com/kendo-ui/mvvm/remote-binding
I don't understand the link between the dropdown and the observable.
InitObservable = function (Id) {
viewModel = kendo.observable({
//create a dataSource
tacheDataSource: new kendo.data.DataSource({
autoSync: true,
transport: {
read: {
url: function () {
return crudServiceBaseUrl + "/Taches?ID=" + Id;
},
method: "GET",
dataType: "json"
}
,
update: {
url: crudServiceBaseUrl + "/Taches",
method: "PATCH",
dataType: "json"
}
,
destroy: {
url: crudServiceBaseUrl + "/Taches/Destroy",
dataType: "json"
}
,
create: {
url: crudServiceBaseUrl + "/Taches",
method: "POST",
dataType: "json"
}
,
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
batch: true,
pageSize: 20,
schema: {
model: {
id: "ID",
fields: TacheFields
}
}
}), // endDatasource
selectedTache: null, //this field will contain the edited dataItem
hasChange: false,
save: function (e) {
this.tacheDataSource.sync();
this.set("hasChange", false);
},
remove: function () {
if (confirm("Etes vous sûr(e) de vouloir supprimer cette tâche ?")) {
this.tacheDataSource.remove(this.selectedTache);
this.set("selectedTache", this.tacheDataSource.view()[0]);
this.change();
}
},
showForm: function () {
return this.get("selectedTache") !== null;
},
change: function () {
this.set("hasChanges", true);
}//,
//cancel: function () {
// this.dataSource.cancelChanges(); //calcel all the change
// validator.hideMessages(); //hide the warning messages
// $("#tacheWindow").data("kendoWindow").close();
//}
});
kendo.bind($("#tacheWindow"), viewModel);
}
I tested the datasource alone with datasource.read(), it works.
What is the trigger of the read of the datasource ?
----- New details
I added
type: "odata-v4"
in the datasource and I updated the schema as this :
e
schema: {
data:function(data){
var toReturn = data.value;
return toReturn;
},
model: {
id: "ID",
fields: TacheFields
}
}
And this to force read()
viewModel.selectedTache = proprietesEcranTache.tacheId;
if (viewModel.showForm()) {
viewModel.tacheDataSource.read();
kendo.bind($("#tacheWindow"), viewModel);
}
I see my answer in network debugger of chrome and I know I receive data in the form witout error but no data are displayed.
Here the oData answer
{
"#odata.context":"http://localhost:14986/odata/$metadata#Taches","value":
[
{
"ID":1,"Description":"D\u00e9marrage application","CreateurId":7,"TypeTacheID":1,"EtatTacheID":6,"ValidantId":null,"DateValidation":null,"EstValidee":false,"CommentaireValidation":null,"EvennementPrecedentID":null
}
]
}
Here is my form
<div id="tacheWindow">
<form id="TacheForm">
<ul class="TacheFormFields">
<li class="">
<div class="formFieldTitle">Id</div>
<div class="formFieldInput textField"><input id="tacheId" type="text" data-bind="value: ID" /></div>
</li>
<li>
<div class="formFieldTitle">Type de tâche</div>
<select id="typesTachesDdl" data-role="dropdownlist"
data-bind="value: TypeTacheID"
data-value-primitive="true"
data-text-field="Nom"
data-value-field="ID"></select>
</li>
<li>
<div class="formFieldTitle">Description</div>
<div class="formFieldInput textField">
<input type="text" data-bind="value: Description" />
</div>
</li>
<li>
<div class="formFieldTitle">Createur</div>
<select id="CreateursDdl" data-role="dropdownlist"
data-bind="value: CreateurId"
data-value-primitive="true"
data-text-field="Nom"
data-value-field="ID"></select>
</li>
<li>
<div class="formFieldTitle">Validant</div>
<select id="ValidantsDdl" data-role="dropdownlist"
data-bind="value: ValidantId"
data-value-primitive="true"
data-text-field="Nom"
data-value-field="ID"
disabled="disabled"></select>
</li>
</ul>
<div class="dialog_buttons">
<button id="TacheFormTemplateSave" data-bind="click: observableSave" class="k-button">Ok</button>
<button id="TacheFormTemplateSave" data-bind="click: observableCancel" class="k-button">Annuler</button>
</div>
</form>
Placing the datasource within your view model simply makes it observable and nothing more, as you have noted. It will only get read when passed to a kendo widget (such as a DropDownList). The telerik demo shows this within the bound html container:
<select data-role="dropdownlist" data-option-label="Select product"
data-value-field="ProductID" data-text-field="ProductName"
data-bind="source: productsSource, value: selectedProduct" style="width: 100%;"></select>
The kendo.bind statement scans the html container for elements with a data-role attribute. In the case above it will find data-role="dropdownlist", instantiate a DropDownList widget and add the necessary html elements for it to the DOM. This part of the declaration:
data-bind="source: productsSource"
...will search for a datasource named 'productsSource' within the view model and assign it to the DropDownList as its datasource to use. The DropDownList will then trigger a read of that datasource in order to populate itself with data.
I created a simple sample that works
Home Page
<div id="editForm">
<table>
<tr>
<td>Id</td>
<td>Nom</td>
</tr>
<tr>
<td>
<input data-role="dropdownlist"
data-auto-bind="false"
data-text-field="Nom"
data-value-field="ID"
data-bind="value: selectedPerson,
source: persons,
visible: isVisible,
enabled: isEnabled,
events: {
change: onChange
}"
style="width: 200px;" />
</td>
<td><input type="text" data-value-update="displaySelectedPerson" data-bind="value: selectedPerson.Nom" class="k-textbox" /></td>
</tr>
</table>
</div>
Important detail : in the text box : data-bind="value: selectedPerson.Nom"
This allow observable to update the field.
Javascript :
var persons = [
{ ID: "1", Nom: "Lolo" },
{ ID: "2", Nom: "Toto" }
];
documentReady = function () {
var viewModel = new kendo.observable({
personsSource: persons
, persons: new kendo.data.DataSource({
data: persons,
schema: {
model: {
fields: {
ID: { type: "number" }
, Nom: { type: "string" }
}
}
}
})
, selectedPerson: null
, hasChange : false
, isPrimitive: false
, isVisible: true
, isEnabled: true
, primitiveChanged: function () {
this.set("selectedPerson", null);
}
, onChange: function () {
console.log("event :: change (" + this.displaySelectedPerson() + ")");
}
, displaySelectedPerson: function () {
var selectedPerson = this.get("selectedPerson");
return kendo.stringify(selectedPerson, null, 4);
}
});
kendo.bind($("#editForm"), viewModel);
}

Select2 (input) value as object after select item

I have a select2 (jQuery plugin) on my code which works normally except for the case when I select an item.
The value is wrong.
Form:
<form id="Teste" method="get" action="">
<input type="hidden" id="e6" name="e6" class="select2" style="width: 600px;" />
<input type="submit" value="Send" />
</form>
Input from select2 - hidden (required for remote data) - value: [Object]:
<input type="hidden" id="e6" name="e6" class="select2 select2-offscreen" style="width: 600px;" tabindex="-1" title="" value="[object Object]">
Javascript used for instance select2:
function formatRes(item) {
return item.Text;
}
function formatSel(item) {
return item.Value;
}
$("#e6").select2({
placeholder: "Select your supplier",
minimumInputLength: 0,
id: function(data){return {id: data.id};},
allowClear: true,
ajax: {
url: "http://localhost:1396/List/_GetDropDownListSupplier",
dataType: 'jsonp',
quietMillis: 300,
data: function (term, page) {
return {
searchString: term,
pageSize: 60,
pageIndex: page,
};
},
results: function (data, page) {
return {results: data.results, more: (page * 60) < data.total };
}
},
formatResult: formatRes,
formatSelection: formatSel,
dropdownCssClass: "bigdrop",
escapeMarkup: function (m) { return m; }
});
Json example returned by ajax to Select2:
{"results":[{"Selected":false,"Text":"Cezar Barbara","Value":"724"},{"Selected":false,"Text":"Cezar Barbara","Value":"765"}],"total":82}
Solved:
id: function(data){return data.Value;}
I was returning a object with id and not a directly value.
Thanks to #mgibsonbr from Stackoverflow PT
You need to use a select element, try this:
<form>
...
<select id="someSelect">
//options
</select>
<input type="hidden" name="fromSelect" id="fromSelect" value=""/>
</form>
You have two options here:
1.- Get the value direct from select:
var selected = $('#someSelect').val();
2.- Assign the value to the hidden input and then get its value:
$('#someSelect').on('change', function(){
$('#fromSelect').attr('value', this.value);
});
var selected = $('#fromSelect').val();

In jquery autocomplete, how to disply label and submit the id corresponding to label

I have a search field which use jquery autocomplete.In this textbox that drops down a list of employee names suggested by the autocomplete.But when my form is submitted I don't want the persons name sent along with form, I want the employee id sent with the form.How I can do that?
<input id="employee">
<input type="hidden" id="employee_id">
Above given is the textfield I used
$(function () {
$.ajax({
url: '/accounts/allEmp',
type: "get",
cache: false,
success: function (data) {
var arr = [];
arr = data.employee;
$("#employee").autocomplete({
minLength: 0,
source: arr,
focus: function (event, ui) {
$("#employee").val(ui.item.name);
return false;
},
select: function (event, ui) {
$("#employee").val(ui.item.name);
$("#employee_id").val(ui.item.id);
return false;
}
})
.data("ui-autocomplete")._renderItem = function (ul, item) {
return $("<li>")
.append("<a>" + item.name)
.appendTo(ul);
};
}
});
});
This is the script I used.While I entering characters in the textfield it doesn't show any results but when remove those characters from textfield it will show all the entities(sorting is not working).And the array look like
array="employee":
[ { "name": "a", "id": 1 },
{ "name": "b", "id": 2 },
{ "name": "c", "id": 3 } ]
Please help me.Thanks in advance.
Do you control server side of source url? If so I suggest you use "value" property name instead of "name" as described in autocomplete api.
Otherwise you can modify that array in place and add "value" properties on the fly.
Here is fiddle I just created from your snippet. With click on "send" it crashes I don't know why but if you look in your developer's panel network request is getting through with params:
employee[name]:Fred
employee[id]:first
DEMO
JS code:
var data = {
json: "{\"employee\":[{\"value\":\"A\",\"id\":\"1\"},{\"value\":\"B\",\"id\":\"2\"},{\"value\":\"C\",\"id\":\"3\"}]}"
}
$(function () {
$('#submit').click(function(){
alert('Employee name = '+$('#employee_name').val()+' Employee id = '+$('#employee_id').val());
});
$.ajax({
url:"/echo/json/",
data: data,
type: "POST",
success:function(data) {
console.log(data);
var arr = data.employee;
$("#employee_name").autocomplete({
minLength: 0,
source: arr,
select: function (event, ui) {
$("#employee_name").val(ui.item.value);
$("#employee_id").val(ui.item.id);
return false;
}
});
}
});
});
HTML code:
<form>
Employee name (Type like "A" or "B" or "C")<br>
<input id="employee_name" name="employee_name">
<br>
Selected Employee id (hidden field):
<input type="text" id="employee_id" name="employee_id" readonly>
<br>
<input type="button" value="Submit" name="submit" id="submit" onclick="check_fields()">

I want to filter in the list if the text box value is changed using knockout

I want to filter in the list if the text box value is changed if the
JSON Returned in Ajax call is as I am using two different model.
Filteration should show hide or just filter the data I am providing you the JSON data what I am getting from the ajax call. Thanks
Data = [{"code":"Grand Financial","cls":"Branch","Chk":true},{"code":"Joan Group","cls":"Branch","Chk":true}]
var searchModel, advisorGroupModel;
$(document).ready(function () {
$.ajax({
type: "GET",
url: '/ASPNET/Reports/GetAdvisorGroups',
dataType: "json",
success: function (data) {
advisorGroupModel = {
advisorGroup: ko.observableArray(data)
};
ko.applyBindings(advisorGroupModel, document.getElementById("advisorGroupModel"));
}
})
var searchModel = {
searchQuery: ko.observable('')
};
searchModel.searchHandle= ko.dependentObservable(function () {
var code = this.searchQuery().toLowerCase();
return ko.utils.arrayFilter(advisorGroupModel, function (beer) {
debugger;
return beer.code.toLowerCase().indexOf(code) >= 0;
});
console.log(search);
}, searchModel)
ko.applyBindings(searchModel, document.getElementById("searchModel"));
});
<div id="searchModel">
<input data-bind="value: searchQuery, valueUpdate: 'keyup'" />
<h6 data-bind="text: searchQuery"></h6>
</div>
<div class="CheckBoxListGroup" id="advisorGroupModel">
<ul data-bind="template: { name: 'advisorGroupTemplate', foreach: advisorGroup, as: 'singleAdvisorGroup' }"></ul>
<script type="text/html" id="advisorGroupTemplate">
<li>
<input type="checkbox" data-bind="attr: { value: code, id: code, checked: Chk }" name="GroupsSel">
<label data-bind="attr: { for: code }, text: '' + code + ' (' + cls + ')' "></label>
</li>
</script>
</div>
don't bind your display to the entire list, bind your display to a computed function that returns the filtered list or returns all items when there are no filters.
then on your keyup call your filterlist function that filters the list removing the ones that do not match your filter

Categories

Resources