Reputation: 25137
Why do I get here in the alert
call an undef
?
#!/usr/bin/env perl
use warnings;
use 5.014;
use utf8;
use Mojolicious::Lite;
use DBI;
my $db = 'my_test_db.db';
my $table = 'my_test_table';
my $dbh = DBI->connect( "dbi:SQLite:dbname=$db", '', '',
{ RaiseError => 1, PrintError => 0, AutoCommit => 1, sqlite_unicode => 1, }
) or die $DBI::errstr;
$dbh->do( "CREATE TEMP TABLE $table ( str TEXT, num INTEGER )" );
my $sth = $dbh->prepare( "INSERT INTO $table ( str, num ) VALUES ( ?, ?)" );
$sth->execute( 'aaa', '111' );
$sth->execute( 'bbb', '222' );
$sth->execute( 'ccc', '333' );
get '/eingabe' => sub {
my $self = shift;
$self->render( 'eingabe' );
};
get '/search_db/:col' => sub {
my $self = shift;
my $col = $self->param( 'col' );
my $term = $self->param( 'term' );
my $sth = $dbh->prepare( "SELECT DISTINCT $col FROM $table WHERE $col LIKE ?" );
$sth->execute( $term . '%');
my $ref;
while ( my $row = $sth->fetchrow_arrayref() ) {
push @$ref, @$row;
}
$self->render( json => $ref );
};
app->start;
__DATA__
@@ eingabe.html.ep
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js"></script>
<script type="text/javascript">
$( document ).ready( function() {
var ids = [ 'str', 'num' ];
for ( var i = 0; i < ids.length; i++ ){
$( "#" + ids[i] ).autocomplete({
source: function( request, response ){
alert( ids[i] ); // <---
$.getJSON( '/search_db/' + ids[i], request, function( data_from_server ){
var suggestions = [];
var len = data_from_server.length;
for( var i = 0; i < len; i++ ){
suggestions.push( data_from_server[i] );
}
response( suggestions );
});
}
});
}
});
</script>
</head>
<body>
<form>
<table>
<tr><td>String:</td><td><input type="text" id="str" name="str"" /></td></tr>
<tr><td>Number:</td><td><input type="number" id="num" name="num" /></td></tr>
</table><br />
<input type="submit" value="OK"/>
</form>
</body>
</html>
Upvotes: 0
Views: 130
Reputation: 11056
It sounds like you're having the problem that's explained here: Creating closures in loops: A common mistake
The reason why you're getting undefined
in your call to alert
is that, when the autocomplete
function is called, your for loop has finished executing meaning your loop variable i
has the value of 2 i.e. ids.length + 1
. Therefore ids[i]
is the same as ids[2]
which doesn't exist as you only have 2 elements in your ids
array. I've tried to come up with a simple demo of this behaviour to help illustrate what's going on: http://jsfiddle.net/ianoxley/KwXVs/1/ (you'll need to have your browser's console open to see the results).
If you create an extra closure that should help preserve your scope and get rid of the undefined
(see http://jsfiddle.net/ianoxley/BVa5Q/).
If you try changing your code to something like this hopefully it will get rid of the problem:
$(document).ready(function () {
function initAutocomplete(element_id) {
$("#" + element_id).autocomplete({
source: function (request, response) {
alert(element_id); // <---
$.getJSON('/search_db/' + element_id, request, function (data_from_server) {
var suggestions = [];
var len = data_from_server.length;
for (var i = 0; i < len; i++) {
suggestions.push(data_from_server[i]);
}
response(suggestions);
});
}
});
}
var ids = ['str', 'num'];
for (var i = 0; i < ids.length; i++) {
var current_id = ids[i];
initAutocomplete(current_id);
}
});
Hope this helps.
Upvotes: 3
Reputation: 711
You source callback function is out of scope. When you attack a function to an event link that it gets called when the event is triggered which is after your for loop has completed.
A good rule of thumb whenever your are using callbacks is to always pass in everything that that function requires or attach everything that object requires to the window object and back it global.
Upvotes: 0
Reputation: 14495
You are defining the i
iteration variable twice: it is used inside of your callback to $.getJSON
call again.
you should rename that one to a different name, j
(just an example).
so it would say:
$( document ).ready( function() {
var ids = [ 'str', 'num' ];
for ( var i = 0; i < ids.length; i++ ){
$( "#" + ids[i] ).autocomplete({
source: function( request, response ){
alert( ids[i] ); // <---
$.getJSON( '/search_db/' + ids[i], request, function( data_from_server ){
var suggestions = [];
var len = data_from_server.length;
for( var j = 0; j < len; j++ ){
suggestions.push( data_from_server[j] );
}
response( suggestions );
});
}
});
}
});
i hope this helps!
Upvotes: 0