Materialize - AutoComplete hiding when changing data with ajax - javascript

I'm making a form using MaterializeCSS and jQuery. I got 2 fields : Name and ID.
The field Name is an AutoComplete field that gets the right data. The ID field is not important.
I'm trying to implement a functionality to get data as the user writes.
The problem occurs when the user writes : the data "behind" the AutoComplete is changing properly, but the dropdown component of the AutoComplete hides. The user must click outside of the AutoComplete field and click back on it to see the changes, which is absolutely not user-friendly.
$(document).ready(function () {
//Autocomplete
$(function () {
$.ajax({
type: 'GET',
url: 'https://reqres.in/api/users?page=1',
success: function (response) {
var nameArray = response.data;
var dataName = {};
console.log('nameArray = ' + JSON.stringify(nameArray, 4, 4));
for (var i = 0; i < nameArray.length; i++) {
dataName[nameArray[i].last_name] = nameArray[i].flag;
}
console.log('dataName = ' + JSON.stringify(dataName, 4, 4));
$('#name_autocomplete').autocomplete({
data: dataName,
limit: 5, // The max amount of results that can be shown at once. Default: Infinity.
});
}
});
});
});
$(document).ready(function () {
$('#name_autocomplete').keyup(function () {
$(function () {
$.ajax({
type: 'GET',
url: 'https://reqres.in/api/users?page=2',
success: function (response) {
var nameArray = response.data;
var dataName = {};
console.log('nameArray = ' + JSON.stringify(nameArray, 4, 4));
for (var i = 0; i < nameArray.length; i++) {
dataName[nameArray[i].last_name] = nameArray[i].flag;
}
console.log('dataName = ' + JSON.stringify(dataName, 4, 4));
$('#name_autocomplete').autocomplete({
data: dataName,
limit: 5, // The max amount of results that can be shown at once. Default: Infinity.
});
}
});
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css" rel="stylesheet"/>
<main>
<div class="container">
<div id="main_panel_form" class="card-panel col s12">
<div class="row">
<form class="col s12" action="/test">
<div class="row">
<div class="input-field col s4">
<input id="name_autocomplete" name="name_autocomplete" type="text" class="autocomplete">
<label id='label_name_autocomplete' for="name_autocomplete" class="active">Name</label>
</div>
<div class="input-field col s3">
<input id="id" name="id" type="text" class="autocomplete">
<label id="label_id" for="id">ID</label>
</div>
</div>
<div class="row center-align">
<button class="btn waves-effect waves-light" type="submit" value="Submit">Submit</button>
</div>
</form>
</div>
</div>
</div>
</main>
On this example, when the user starts to write, it gets new data (from ?page=1 to ?page=2)
I'd like to see the data of the AutoComplete change while it remains opened.
I've also made an example on Codepen

The AutoComplete component hides each time the user writes because you initialize #name_autocomplete for each keyup. Each time the init function is called, it closes the autocomplete suggestions.
Materialize has a specific method updateData to refresh the initial object provided: http://materializecss.com/autocomplete.html
I took your codePen and refactored it so you can have an example of the autocomplete method updateData. Codepen

Related

autocomplete on click updates the same value on second input box

Could someone plz help me out here as most of the things looks ok like fetching matching results from database but then when i click on value on both input box the same autocomplete value gets added.
could someone please help me fix this issue?
here is my html:
<div class="col-sm-12">
<label class="form-label-outside">From</label>
<div class="form-wrap form-wrap-inline">
<input id="from-input" class="form-input" name="from" type="text">
<div id="from-show-list" class="list-group"></div>
</div>
</div>
<div class="col-sm-12">
<label class="form-label-outside">To</label>
<div class="form-wrap form-wrap-inline">
<input id="to-input" class="form-input" name="to" type="text">
<div id="to-show-list" class="list-group"></div>
</div>
</div>
my js
<script src="js/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#from-input").keyup(function() {
let searchText = $(this).val();
if (searchText != "") {
$.ajax({
url: "airports.php",
method: "post",
data: {
query: searchText,
},
success: function(response) {
$("#from-show-list").html(response);
},
});
} else {
$("#from-show-list").html("");
}
});
// Set searched text in input field on click of search button
$(document).on("click", "a", function() {
$("#from-input").val($(this).text());
$("#from-show-list").html("");
});
});
$(document).ready(function() {
$("#to-input").keyup(function() {
let searchText = $(this).val();
if (searchText != "") {
$.ajax({
url: "airports.php",
method: "post",
data: {
query: searchText,
},
success: function(response) {
$("#to-show-list").html(response);
},
});
} else {
$("#to-show-list").html("");
}
});
// Set searched text in input field on click of search button
$(document).on("click", "a", function() {
$("#to-input").val($(this).text());
$("#to-show-list").html("");
});
});
</script>
and here is the php
require_once 'includes/config.php';
if (isset($_POST['query'])) {
$inpText = $_POST['query'];
$sql = 'SELECT * FROM pt_flights_airports WHERE cityName LIKE ? OR name LIKE ? OR code LIKE ?';
$stmt = $db->prepare($sql);
$stmt->execute(array('%'.$inpText.'%','%'.$inpText.'%','%'.$inpText.'%'));
$result = $stmt->fetchAll();
if ($result) {
foreach ($result as $row) {
echo ''.$row['cityName'].' ('.$row['code'].') - <small>'.$row['name'].'</small>';
}
} else {
echo '<p class="list-group-item border-1">Airport not listed!</p>';
}
}
Appreciate your help
The issue arises due to the click function on link. Define two separate groups of links by specifying the id of the div that contains those links.
// Set searched text in input field on click of search button
$(document).on("click", "#from-show-list a", function() {
$("#from-input").val($(this).text());
$("#from-show-list").html("");
});
// Set searched text in input field on click of search button
$(document).on("click", "#to-show-list a", function() {
$("#to-input").val($(this).text());
$("#to-show-list").html("");
});
Apply max height to the results div using css like this.
<div id="from-show-list" class="list-group" style="max-height: 100px; overflow: auto;"></div>
<div id="to-show-list" class="list-group" style="max-height: 100px; overflow: auto;"></div>

Triggering JavaScript by hitting enter, enabling multiple searches/AJAX queries/DataTable displays without refreshing web page

I have a web page with an AWS API interface to query an RDS Aurora MySQL Serverless database. When a user types in a SQL statement and hits the Query button, an AJAX request will be triggered, JSON will be returned and the test-table table below will be converted to a DataTable.
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<p>Please enter a SQL query below</p>
<p>Do not wrap your query in outer quotation marks.</p>
<p>For database structure information, please select "Learn About the Database" above.</p>
</div>
</div>
<div class="row">
<div class="col-xs-11 col-sm-11 col-md-11 col-lg-11">
<div class="active-cyan-4 mb-4">
<input id="sql-placeholder" class="form-control" type="text" placeholder="Write SQL here..." aria-label="Search">
</div>
</div>
<div class="col-xs-1 col-sm-1 col-md-1 col-lg-1">
<button id="query-button" type="button" class="btn btn-primary" onclick="DisplayQuery()">Query</button>
</div>
</div>
</div>
<div class="container-fluid">
<table id="test-table" class="table table-striped table-bordered dt-responsive nowrap" cellspacing="0" width="100%">
</table>
</div>
The JavaScript for the onclick="DisplayQuery()" function is below.
var DisplayQuery;
(function($) {
DisplayQuery = function() {
$.ajax({
method: 'POST',
url: '*****',
beforeSend: function(xhr) {
xhr.setRequestHeader("access-control-allow-origin", "*")
},
data: JSON.stringify({
"sqlStatement": $('#sql-placeholder').val()
}),
contentType: 'application/json',
success: function(response) {
// Get columns labels as list of dictionaries colLabels
var colLabels = [];
for (i = 0; i < response.sqlStatementResults[0].resultFrame.resultSetMetadata.columnMetadata.length; i++) {
colLabels.push({
title: response.sqlStatementResults[0].resultFrame.resultSetMetadata.columnMetadata[i].name
});
};
// Get data rows as array of arrays dataRows3
var dataRows = response.sqlStatementResults[0].resultFrame.records;
var dataRows2 = [];
var dataRows3 = [];
for (i = 0; i < dataRows.length; i++) {
dataRows2.push(dataRows[i].values);
};
dataRows2.forEach(arr => {
rowVals = [];
arr.forEach(e => {
Object.entries(e).forEach(k => rowVals.push(k[1]))
});
dataRows3.push(rowVals);
});
try {
$('#test-table').destroy();
} finally {
// Write DataTable from colLabels and dataRows3
$('#test-table').DataTable({
data: dataRows3,
columns: colLabels,
scrollX: true
});
}
},
error: function ajaxError(error) {
console.error('Error in query processing; please try again.');
}
})
}
}(jQuery));
Is there a way to add to/rewrite this JavaScript so that the query can also be triggered by typing into the sql-placeholder and hitting enter instead of clicking on the query-button? Also, is there a way to allow multiple searches without having to reload the web page? In other words, if you query, then go type something new into the sql-placeholder and hit enter or click the query-button, a new query will be triggered, the previous results will be removed, and the new results will be displayed?
You can use the keydown event listener to check which key the user typed and if the key used was the one you want (in this case Enter) call the function.
onkeypress reference
For example:
document.getElementById('#sql-placeholder').onkeypress = function(e) {
var keyCode = e.keyCode || e.which
if (keyCode === '13') {
// Enter pressed
DisplayQuery()
}
}
Either wrap them in a form and catch the submit event as Nick mentioned or a simple way is
$('#sql-placeholder').keypress(function(e) {
if(e.which == 10 || e.which == 13) {
DisplayQuery();
}
})

Hide is not working in Ajax

I am not a techie in terms of html or ajax or javascript. But i had to develop a script. My problem is "hide" is not working in my ajax.
I have 2 text field that gives the search result. I want to hide the search suggestion (in "ul" tag) of one when the user searches in the other.
Below given is the javascript and html
function autocomplet() {
var min_length = 0; // min caracters to display the autocomplete
var keyword = $('#country_id').val();
if (keyword.length >= min_length) {
$.ajax({
url: 'ajax_refresh.php',
type: 'POST',
data: {keyword:keyword},
success:function(data){
$('#country_list_id').show();
$('#country_list_id').html(data);
}
});
} else {
$('#country_list_id').hide();
}
document.getElementById('house_list_id').style.display = 'none';
}
function autocomplet_house() {
var min_length = 0; // min caracters to display the autocomplete
var keyword = $('#house_id').val();
if (keyword.length >= min_length) {
$.ajax({
url: 'ajax_refresh_house.php',
type: 'POST',
data: {keyword:keyword},
success:function(data){
$('#house_list_id').show();
$('#house_list_id').html(data);
}
});
} else {
$('#house_list_id').hide();
}
document.getElementById('country_list_id').style.display = 'none';
}
<form>
<div class="label_div">Search Name:&nbsp </div>
<div class="input_container">
<input type="text" id="country_id" name="country_name" autocomplete="off" onkeyup="autocomplet()">
<ul id="country_list_id"></ul>
</div>
<div class="label_div">Search House:&nbsp </div>
<div class="input_container">
<input type="text" id="house_id" name="house_name" autocomplete="off" onkeyup="autocomplet_house()">
<ul id="house_list_id"></ul>
</div>
</form>
It seems like you have a hide-condition, that is never met:
var min_length = 0;
if (keyword.length >= min_length){
/* keyword is always zero length or greater */
} else {
/* will never reach here */
}
Besides, I think you want to hide 'the other list', when showing the 'current list' ... Try changing your ajax-success like this:
success:function(data){
$('#country_list_id').html(data).show();
$('#house_list_id').hide();
}
success:function(data){
$('#house_list_id').html(data).show();
$('#country_list_id').hide();
}
Ok ... I have been thinking, and have rearranged everything.
Try this:
<script>
function autocomplet(Elm){
var Name = Elm.attr('name');
var Word = Elm.val();
var ListA = $('#'+Name+'_list_id');
var ListB = Elm.parents('form').find('ul').not(ListA).hide();
var min = 0; // min caracters to display the autocomplete
if( Word.length >= min ){
$.ajax({
url: 'ajax_refresh_'+Name+'.php',
type: 'POST',
data: {Word:Word},
success:function(data){
ListA.empty().html(data).show();
}
});
}
}
</script>
<form>
<div class="label_div">Search Name:&nbsp</div>
<div class="input_container">
<input type="text" name="country" autocomplete="off" onkeyup="autocomplet($(this));">
<ul id="country_list_id"></ul>
</div>
<div class="label_div">Search House:&nbsp</div>
<div class="input_container">
<input type="text" name="house" autocomplete="off" onkeyup="autocomplet($(this));">
<ul id="house_list_id"></ul>
</div>
</form>
Thanks a lot OLA, you gave me an idea to reduce the redundancy of the code. I've Cleared my browsing history and it worked.

Javascript, amend elements after clone

Im trying to post a cloned section of a form but it doesnt submit all due to element names being identical.
Does anyone know the best process for changing input name attributes during a clone ?
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
if (checkMACAddress()==true) {
$("#test").clone().insertAfter("div.test-row:last");
}
});
});
function checkMACAddress() {
var valid = true;
for ( var i = 0, l = document.getElementsByName("mac").length; i < l; i++ ) {
var macAddress=document.getElementsByName("mac")[i].value;
var macAddressRegExp=/^(?:[0-9A-F]{2}[:]?){5}(?:[0-9A-F]{2}?)$/i;
if (macAddressRegExp.test(macAddress)==false) { //if match failed
alert("MAC Invalid - Must be IEEE.802 example 00:3F:00:10:00:2C");
valid=false;
}
}
return valid;
}
</script>
<h3>Account Details</h3>
<div class="row">
<div class="columns small-4">
<label>Destination Account Number*</label>
[[input||type=text||name=Account||name_literal=Account||placeholder=12345||required=required]]
</div>
</div>
<hr>
<h3>Device Details</h3>
<h5>
<button type='button'>Add Device</button>
</h5>
<div id="test" class="test-row">
<div class="columns small-3">
<label>MAC - IEEE.802 Format Only</label>
[[input||type=text||name=mac||name_literal=mac||placeholder=54781A139264||required=required]]
</div>
<div class="columns small-3">
<label>Extension/Seat Number</label>
[[input||type=text||name=seat||name_literal=seat||placeholder=200]]
</div>
<div class="columns small-3">
<label>Display Name</label>
[[input||type=text||name=station||name_literal=station||placeholder=reception desk]]
</div>
One way could be to work with an array syntax as field name, for example: data[identifier][]. Otherwise you'll need to modify the name attribute after cloning:
var c = 0;
// each time you click on the button...
$(".clone").on('click',function(){
// generate a new clone of complete test div..
var klon = $( '#test').clone();
// append it to parent element (or after existing, as you like)
$('#test').parent().append(klon);
// increase global counter...
c++;
// inside clone find all inputs
// (if you other form elements, you must add them in selector)
klon.find('input').each(function() {
var $this = $(this),
name = $this.attr('name');
// update name attribute
$this.attr('name', name + '_' + (c));
});
});
See a fiddle here.
I still prefer the name / array solution, it is easier to handle server-side, because you can loop over the fields instead of asking for unkown amount of new fields.

Cannot Click button on webpage

Is there any reason why the prompt will not appear when clicking the bottom on my web page? The other buttons works on my web page fine but the "create room" button will not work and I am not sure why.
Any Ideas?
ViewBag.Title = "Chat";
}
<h2>General Chat</h2>
<div id="wrapper">
<div id="upper-wrapper">
<div id="available-rooms-dialog">
<h4>Available Rooms</h4>
<input type="button" onclick="s = prompt('Enter a new Room Name', 'Name');" id=" createroom" value="Create Room" />
</div>
<div id="discussion-dialog">
<textarea rows="30" cols="50" id="discussion"></textarea>
</div>
</div>
<div id="message-dialog">
<textarea rows="3" id="message">Type your message</textarea>
<br/>
<input type="button" id="sendmessage" value="Post" />
<input type="hidden" id="displayname" />
<input type="checkbox" id="enter-sends-message"/>
Enter sends message
</div>
</div>
#section scripts {
<!--Script references. -->
<!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
<!--Reference the SignalR library. -->
<script src="~/Scripts/jquery.signalR-2.0.2.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>
<!--SignalR script to update the chat page and send messages.-->
<script type="text/javascript">
var json;
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
//TODO: Add Record to Server
$.ajax(
{
type: "Post",
url: "#Url.Action("AddMessage", "Home")",
data: { messageCont: message.toString() },
success: function (data) {
for (var i = 0; i < data.length; i++) {
//access with data[i].modelattribute
}
}
});
$.ajax(
{
type: "Get",
url: "#Url.Action("GetMessages", "Home")",
success: function (data) {
json = data;
var obj = JSON.parse(json);
for (var i = 0; i < data.length; i++) {
//access with data[i].modelattribute
$('#discussion').append(htmlEncode(obj[i].Author) + " : " + htmlEncode(obj[i].Message) + "\r\n");
}
}
});
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
}

Categories

Resources