autocomplete How to avoid duplicate selection - javascript

I am using JQuery autocomplete. In which i want to avoid duplicate selection of pre-selected and pre-located (pre fetched) list.
The following script works with currently selected list. But how can I do it with pre-located list which are fetched with document onload.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
JS
$(document).on('focus','.search',function(){
let type = $(this).data('type');
$(this).autocomplete({
source: function( request, response ) {
$.ajax({
url : 'autocomplete.php',
dataType: "json",
method: 'post',
data: {
name_startsWith: request.term,
type: type
},
success: function( data ) {
let selected = [],
uniques = [],
choices = [];
$('tr .search[id^="name_"]').each(function(){
let value = this.value.trim().toLowerCase();
if (value && selected.indexOf(value) < 0) {
selected.push(value);
}
});
data.forEach(item => {
let value = item.name.trim().toLowerCase();
if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
choices.push({
label: item.name,
value: item.name,
data: item,
type: 'name'
});
uniques.push(value);
}
});
response(choices);
}
});
},
autoFocus: true,
minLength: 1,
select: function( event, ui ) {
// Strips the 'team_' part, leaving just the number.
let id_num = $(this).attr('id').substring(5);
$(this).val(ui.item.value);
$('#id_' + id_num).val(ui.item.data.id).change();
$('#marks_' + id_num).val(ui.item.data.marks);
$(this).attr('data-type', ui.item.type);
return false;
},
appendTo: $(this).parent()
});
});
HTML
<table class="table table-bordered table-hover" id="pat_tests">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Marks</th>
</tr>
</thead>
<tbody>
<tr>
<td> <input type="number" id="id_1"> </td>
<td><input type="text" id="name_1" class="search" data-type="type"></td>
<td><input type="number" id="marks_1" ></td>
</tr>
<tr>
<td> <input type="number" id="id_2"> </td>
<td><input type="text" id="name_2" class="search" data-type="type"></td>
<td><input type="number" id="marks_2" ></td>
</tr>
<tr>
<td> <input type="number" id="id_3"> </td>
<td><input type="text" id="name_3" class="search" data-type="type"></td>
<td><input type="number" id="marks_3" ></td>
</tr>
</tbody>
</table>
<h2>Pre Selected List of Students</h2>
<p class="selected">Mario</p>
<p class="selected">Nico"</p>
<p class="selected">Mento</p>
PHP
if(!empty($_POST['type'])){
$type = $_POST['type'];
$name = $_POST['name_startsWith'];
$query = $db->prepare("SELECT id, name, marks FROM class where (name LIKE '".$name."%') ");
$query->execute();
$data = array();
$i = 0;
while ($row = $query->fetch(PDO:: FETCH_ASSOC)) {
$data[$i]['id'] = $row['id'];
$data[$i]['name'] = $row['name'];
$data[$i]['marks'] = $row['marks'];
++$i;
}
echo json_encode($data);

I recommend to use an array in Js, you can put preselected in it. and then use it to verify if not selected already push in it then you can add to your dom.
so in js you would have something like
var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];
above code in firs line of script make an array of empty or already selected if selected is not empty
then you can use it to check if an item is selected or not. also it's better to use $selected = array_map('strtolower', $selected); before in php (according to your code)
EDIT
<script type="text/javascript">
//in case you have php array of already selected items. remove it if $selected is not provided in php.
//var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];
var selected = [];
$(".selected").each(function(index, value){
selected.push($(this).text().trim().toLowerCase());
});
$(document).on('focus', '.search', function (e) {
let type = $(this).data('type');
$(this).autocomplete({
source: function (request, response) {
$.ajax({
url: 'your url',
dataType: "json",
method: 'post',
data: {
name_startsWith: request.term,
type: type
},
success: function (data) {
let uniques = [],
choices = [];
data.forEach(function (item) {
let value = item.name.trim().toLowerCase();
if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
choices.push({
label: item.name,
value: item.name,
data: item,
type: 'name'
});
uniques.push(value);
}
});
response(choices);
}
});
},
autoFocus: true,
minLength: 1,
select: function (event, ui) {
// Strips the 'team_' part, leaving just the number.
let id_num = $(this).attr('id').substring(5);
$(this).val(ui.item.value);
$('#id_' + id_num).val(ui.item.data.id).change();
$('#marks_' + id_num).val(ui.item.data.marks);
$(this).attr('data-type', ui.item.type);
selected.push(ui.item.value.trim().toLowerCase());
return false;
},
appendTo: $(this).parent()
});
});
</script>
dont wory if you load js as an external file. just make sure define
<script>
var selected = [<?= !empty($selected) ? '"'.implode('","', $selected).'"' : '' ?>];
</script>
before it.

Updated answer:
Because you changed your HTML a solution could be based on:
if ($('.selected:contains(' + value + ')').length == 0) {
The updated snippet:
$(document).on('focus', '.search', function (e) {
let type = $(this).data('type');
$(this).autocomplete({
source: function (request, response) {
$.ajax({
url: 'https://api.github.com/repositories?since=364',
dataType: "json",
method: 'get',
data: {
name_startsWith: request.term,
type: type
},
success: function (data) {
data = data.map((a) => ({name: a.name || ''})).filter((e) => e.name.indexOf('_') == -1);
let selected = [],
uniques = [],
choices = [];
$('tr .search[id^="name_"]').each(function () {
let value = this.value.trim().toLowerCase();
if (value && selected.indexOf(value) < 0) {
selected.push(value);
}
});
data.forEach(function (item) {
let value = item.name.trim().toLowerCase();
if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
if ($('.selected:contains(' + value + ')').length == 0) {
choices.push({
label: item.name,
value: item.name,
data: item,
type: 'name'
});
uniques.push(value);
}
}
});
response(choices);
}
});
},
autoFocus: true,
minLength: 1,
select: function (event, ui) {
// Strips the 'team_' part, leaving just the number.
let id_num = $(this).attr('id').substring(5);
$(this).val(ui.item.value);
$('#id_' + id_num).val(ui.item.data.id).change();
$('#marks_' + id_num).val(ui.item.data.marks);
$(this).attr('data-type', ui.item.type);
return false;
},
appendTo: $(this).parent()
});
});
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<table class="table table-bordered table-hover" id="pat_tests">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Marks</th>
</tr>
</thead>
<tbody>
<tr>
<td> <input type="number" id="id_1"> </td>
<td><input type="text" id="name_1" class="search" data-type="type"></td>
<td><input type="number" id="marks_1" ></td>
</tr>
<tr>
<td> <input type="number" id="id_2"> </td>
<td><input type="text" id="name_2" class="search" data-type="type"></td>
<td><input type="number" id="marks_2" ></td>
</tr>
<tr>
<td> <input type="number" id="id_3"> </td>
<td><input type="text" id="name_3" class="search" data-type="type"></td>
<td><input type="number" id="marks_3" ></td>
</tr>
</tbody>
</table>
<h2>Pre Selected List of Students</h2>
<p class="selected">invisible</p>
<p class="selected">tinder</p>
<p class="selected">ike</p>
Try to select tinder, just for a test.
Old answer:
First issue: you initialize the autocomplete on every focus event! Please, avoid to initialize it more times.
If I understood correctly, you want to remove from the autocomplete list elements having a value already contained in one of the Pre Selected List of Students.
If so, you can add, before the choices.push({ a test:
if ($('.selected:text[value="' + item.name + '"]').length == 0) {
Full code:
$(document).on('focus', '.search', function (e) {
let type = $(this).data('type');
$(this).autocomplete({
source: function (request, response) {
$.ajax({
url: 'your url',
dataType: "json",
method: 'post',
data: {
name_startsWith: request.term,
type: type
},
success: function (data) {
let selected = [],
uniques = [],
choices = [];
$('tr .search[id^="name_"]').each(function () {
let value = this.value.trim().toLowerCase();
if (value && selected.indexOf(value) < 0) {
selected.push(value);
}
});
data.forEach(function (item) {
let value = item.name.trim().toLowerCase();
if (uniques.indexOf(value) < 0 && selected.indexOf(value) < 0) {
if ($('.selected:text[value="' + item.name + '"]').length == 0) {
choices.push({
label: item.name,
value: item.name,
data: item,
type: 'name'
});
uniques.push(value);
}
}
});
response(choices);
}
});
},
autoFocus: true,
minLength: 1,
select: function (event, ui) {
// Strips the 'team_' part, leaving just the number.
let id_num = $(this).attr('id').substring(5);
$(this).val(ui.item.value);
$('#id_' + id_num).val(ui.item.data.id).change();
$('#marks_' + id_num).val(ui.item.data.marks);
$(this).attr('data-type', ui.item.type);
return false;
},
appendTo: $(this).parent()
});
});

Related

JQuery Datatable Reload From Server MVC

I have a Datatable of JQuery generated at first-page load. I am trying to refresh it according to the selected criteria from the selectlist.
My Datatable initialized first like the following code.
<table class="table table-striped table-hover" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Select All <input type="checkbox" class="checkbox" id="chkBoxAll"></th>
#foreach (System.Data.DataColumn col in Model.DataTypesTable.Columns)
{
<th> #col.Caption</th>
}
</tr>
</thead>
<tbody>
#foreach (System.Data.DataRow row in Model.DataTypesTable.Rows)
{
<tr>
<td> <input type="checkbox" class="checkbox" name="chkBox" value="#row.ItemArray[0]"></td>
#foreach (var cell in row.ItemArray)
{
<td>
#cell.ToString()
</td>
}
</tr>
}
</tbody>
</table>
<script>
$(document).ready(function() {
$('#dataTable').DataTable();
});
</script>
It initializes well at first. However, when I try to reload it on the selectlistchange event, it doesn't reload anything and displays an error like this.
DataTables warning: table id=dataTable - Requested unknown parameter 'Id' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4
<script type="text/javascript">
$("#slctDeviceList").change(function () {
var selectedValue = $("#slctDeviceList option:selected").text();
$.ajax({
traditional: true,
dataType: 'html',
type: "GET",
url: '#Url.Action("GetDeviceDataTypes", "Home")',
data: { slctDeviceList: selectedValue },
success: function (result) {
console.log("Success");
console.log(result);
$("#dataTable").DataTable({
destroy: true,
data: result,
columns: [
{ data: "Id", name: "Id" },
{ data: "Data Name", name: "Data Name" },
{ data: "Description", name: "Description" },
{ data: "Device Type", name: "Device Type" }
], columnDefs: [{
"defaultContent": "-",
"targets": "_all"
}]
});
},
error: function (result) {
console.log("error");
}
});
});
</script>
Controller:
public JsonResult GetDeviceDataTypes(string slctDeviceList)
{
ChartRepository repository = new ChartRepository();
System.Data.DataTable dt = repository.GetDataTypes(slctDeviceList);
var json = this.Json(new { data = dt }/*, _jsonSetting*/);
return json;
}
My data is like below from the developer tools:
Please help me out to resolve the issue... Thanks in advance.
After long tries and losing hairs.. I have found a solution clear and add the rows again instead of destroy command. Here is the solution below.
<script type="text/javascript">
$("#slctDeviceList").change(function () {
var selectedValue = $("#slctDeviceList option:selected").text();
$.ajax({
traditional: true,
dataType: 'json',
type: "GET",
url: '#Url.Action("GetDeviceDataTypes", "Home")',
data: { slctDeviceList: selectedValue },
success: function (result) {
console.log("Success");
var dataTable = $("#dataTable").DataTable();
dataTable.clear().draw();
$.each(result, function myfunc (index, value) {
// use data table row.add, then .draw for table refresh
dataTable.row.add([
'<input type="checkbox" class="checkbox" name="chkBox" value="' + value.Id + '">',
value.Id,
value.DataName,
value.Description,
value.DeviceType
]).draw();
});
},
error: function (result) {
console.log("error");
}
});
});
</script>
Also, it is important to return a json object from the controller action.
PS. If the Json Object has an initial tag like data, you may need to change the looping value.Id to value.data.Id. But it is better to not use any tag.
public JsonResult GetDeviceDataTypes(string slctDeviceList)
{
ChartRepository repository = new ChartRepository();
System.Data.DataTable dt = repository.GetDataTypes(slctDeviceList);
JsonSerializerSettings _jsonSetting = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore };
var json = this.Json(dt , _jsonSetting);
return json;
}

Insert a toggle switch value into DB via Ajax - MVC

I have CheckBox which is working like Toggle Switches and by default it is set Checked/ON and when i UnChecked/OFF the CheckBox,it will pass the value (OFF) not problem , but when i Checked the Checkbox again it cant pass the value (ON).
Can anyone please help me or point me in the right direction!
Thanks in advance :)
Example With ScreenShots:
By Default it is set Checked/ON
Now I UnChecked/OFF , its pass the Value
Now i Checked/ON again, it cant pass the Value
View:
<tbody>
#foreach (var rma in Model)
{
<tr>
<td>
<label class="switch switch-text switch-primary switch-pill">
<input type="checkbox" class="switch-input" checked>
<span data-on="ON" data-off="OFF" class="switch-label"></span>
<span data-id="#rma.Id" class="switch-handle"></span>
</label>
</td>
</tr>
}
</tbody>
JavaScript:
<script>
$(document).ready(function () {
$('.switch-handle').click(function () {
var Id = $(this).data('id');
var checkStatus = this.checked ? 'ON' : 'OFF';
$.ajax({
type: "POST",
url: '#Url.Action("UpdateNtf", "Account")',
data: {
id: Id,
status: checkStatus
},
dataType: 'json',
success: function (result) {
if (result) {
console.log("Ok");
} else {
console.log("error");
}
},
error: function () {
console.log('something went wrong - debug it!');
}
})
});
});
</script>
Controller:
public JsonResult UpdateNtf(int? id, string status)
{
var result = db.RMA_History.Where(a => a.Id == id).FirstOrDefault();
if (result != null)
{
result.NTFOnOFF = status;
db.SaveChanges();
}
return Json(result,JsonRequestBehavior.AllowGet);
}

I do not know why this Java Script code not run in MVC

In dropdownlist onchange event call FillSystem() Ajax Request is sent but scopeId selector do not run this below method.
function FillSystem() {
var _scopeId = $('#ScopeId').val();
var _roleId = $('#Role_Id').val();
$.ajax({
url: '/Account/FillSystem',
type: "GET",
dataType: "JSON",
data: { scopeId: _scopeId, roleId: _roleId },
success: function (systems) {
$("#SystemId").html(""); // clear before appending new list
$.each(systems, function (i, system) {
$("#SystemId").append(
$('<option></option>').val(system.System_Id).html(system.SystemName));
});
}
});
}
<table class="table w3-striped w3-border w3-card-4" style="width: 65%">
<tr>
<td>
Scope
</td>
<td>
#Html.DropDownList("ScopeId", null,"--Please Select--", new { style = "width:250px", #onchange = "FillSystem()" })
</td>
</tr>
<tr>
<td>System</td>
<td>
#Html.DropDownList("SystemId", null, "--please select--", new { style = "width:250px" })
</td>
</tr>
</table>
you use DropDown in table and probably multiple row exist, and multiple id with same, your $('#ScopeId') selector, select first element with ScopeId.
first remove #onchange = "FillSystem()" from DropDownList, then try this code
(function ($) {
function FillSystem() {
var _scopeId = $(this).val();
var _roleId = $('#Role_Id').val();
var $row = $(this).closest("tr");
$.ajax({
url: '/Account/FillSystem',
type: "GET",
dataType: "JSON",
data: { scopeId: _scopeId, roleId: _roleId },
success: function (systems) {
$("#SystemId", $row).html(""); // clear before appending new list
$.each(systems, function (i, system) {
$("#SystemId", $row).append(
$('<option></option>').val(system.System_Id).html(system.SystemName));
});
}
});
}
$(function () {
$("table").on("change", "#ScopeId", FillSystem)
});
}(jQuery));

Angular.js $http.post with Codeigniter not working

I'm trying to submit a new post using $http. it's not working. I tried the shore version and the long version, both fail. console:" Failed to load resource: the server responded with a status of 500 (Internal Server Error) "
This my code:
$scope.doAdd = function(){
$http({
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: 'api/addduans',
method: "POST",
})
.success(function(data) {
alert('OK');
});
}
My controller:
function addduans_post()
{
$id_duan = $this->post('id_duan');
$title = $this->post('title');
$addr = $this->post('addr');
$dis = $this->post('dis');
$img_duan = $this->post('img_duan');
$result = $this->admin_model->add_id_da($id_duan,$title,$addr,$dis,$img_duan);
if($result === FALSE)
{
$this->response(array('status' => 'failed'));
}
else
{
$this->response(array('status' => 'success'));
}
}
My Model:
public function add_id_da($id_duan,$title,$addr,$dis,$img_duan)
{
$data = array(
'id_duan' => $id_duan,
'title' => $title,
'addr' => $addr,
'dis' => $dis,
'img_duan' => $img_duan
);
$this->db->insert('duan_test', $data);
}
This my view :
<tr>
<td> <input name='id_duan' style='width: 50px' ng-model='id_duan'/> </td>
<td> <input name='title' ng-model='title'/> </td>
<td> <input name= 'addr' ng-model='addr'/> </td>
<td> <input name='dis' style='width: 60px' ng-model='dis'/> </td>
<td> <input name='img_duan' ng-model='file_name'/> </td>
<td> Add </td>
</tr>
Anyone got any idea on how to make this work? Thanks!
Step 1: Make your input fields into a form.
<form ng-submit='doAdd()'>
<tr>
<td> <input name='id_duan' style='width: 50px' ng-model='myForm.id_duan'/> </td>
<td> <input name='title' ng-model='myForm.title'/> </td>
<td> <input name= 'addr' ng-model='myForm.addr'/> </td>
<td> <input name='dis' style='width: 60px' ng-model='myForm.dis'/> </td>
<td> <input name='img_duan' ng-model='myForm.file_name'/> </td>
<td> <input type="submit" class="btn - btn-info" value="add"> </td>
</tr>
</form>
Step 2: Submit the form
$scope.formData = {};
$scope.doAdd = function(){
$http({
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: 'api/addduans',
method: "POST",
data : $.param($scope.formData)
})
.success(function(data) {
alert('OK');
});
}
Hope it helps. You seem to be switching from jQuery. Refer here for a simple tutorial.
I faced such condition. I have used custom serialize service as following . it may be use for your problem.
appCommonServiceModule.factory('SerialiazeService', function () {
function SeriliazeService() {
this.serialiaze = function (obj, prefix) {
var str = [];
for (var p in obj) {
var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push(typeof v == "object" ? this.seriliaze(v, k) : encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
return str.join("&");
};
}
return new SeriliazeService();
});
it is used in $http.post like that (memberModel is javascript object data type):
$http.post(BASE_URL + 'index.php/signUp', SerialiazeService.serialiaze(memberModel), {responseType: 'json', headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
change this code
$http({
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
url: 'api/addduans',
method: "POST",
data : $.param($scope.formData)
})
to this:
var request = $http.post('api/addduans', $.param($scope.formData), {headers : {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'}});

Jquery ui autocomplete not fill

I'm new to JQuery and jQuery UI.
I'm using autocomplete with remote json in a table with dynamically rows.
The problem is: everything works, but for some reasons, the input code isn't filled.
The curious thing is that if I hardcode #code0 or #code1 in select area, it works.
But it seem #code+i isn't recognized in select. Another strange thing is $("#product"+i) works.
Can someone help a JS beginner?
$(document).ready(function(){
var i=0;
$("#add_row").click(function(){
$('#addr'+i).html("<td>"+ (i+1) +"<\/td><td><input id='product"+i+"' name='product"+i+"' type='text' placeholder='Digita il codice o il nome del prodotto' class='form-control input-md' /> <\/td><td><input id='code"+i+"' name='code"+i+"' type='text' placeholder='Codice' class='form-control' readonly='readonly'><\/td>");
$('#tab_logic').append('<tr id="addr'+(i+1)+'"><\/tr>');
$("#product"+i).autocomplete({
source: function( request, response ) {
$.ajax({
url: "productsearch.php",
dataType: "json",
data: {term: request.term},
success: function(data) {
response($.map(data, function(item) {
return {
label: item.text,
id: item.id,
code: item.id
};
}));
}
});
},
minLength: 2,
select: function(event, ui) {
var codice="$code"+i;
$('#codice').val(ui.item.id);
}
});
i++;
});
$("#delete_row").click(function(){
if(i>1){
$("#addr"+(i-1)).html('');
i--;
}
});
$("#product"+i).autocomplete({
source: function( request, response ) {
$.ajax({
url: "productsearch.php",
dataType: "json",
data: {term: request.term},
success: function(data) {
response($.map(data, function(item) {
return {
label: item.text,
id: item.id,
code: item.id
};
}));
}
});
},
minLength: 2,
select: function(event, ui) {
$("#code"+i).val(ui.item.id);
}
});
i++;
});
});
<tbody>
<tr id='addr0'>
<td>1</td>
<td><input id="product0" type="text" name='product0' placeholder='Digita il codice o il nome del prodotto' class="form-control"></td>
<td><input id="code0" type="text" name='code0' placeholder='Codice' class="form-control" readonly="readonly"></td>
</tr>
<tr id='addr1'>
</tr>
One thing for sure is that in your select event handler on the first autocomplete, you have a bug:
select: function(event, ui) {
var codice="$code"+i;
$('#codice').val(ui.item.id);
}
You create a variable for the jquery selector and then don't use it. You can't update your input value whose id is "code"+i with this function. Instead, it needs to be:
select: function(event, ui) {
var codice="#code"+i;
$(codice).val(ui.item.id);
}
Fix that and see if your problem goes away.
I've solved by adding a new var count=0; at the top.
Now I use:
$("[id^=code]:eq( " + count + " ) ").val(ui.item.id);
the problem is the variable i
Thank you everyone for the help
select: function(event, ui) {
$("[id^=code]:eq( " + count + " ) ").val(ui.item.id);
}
});
i++;
count++;
});

Categories