Reputation: 627
I'm using jQuery Autocomplete with categories, I've used the demo code which worked fine, now i'm trying to populate the drop down with data from my database. I've used this code within my view:
:javascript
$(function() {
var data = [
- Datasheet.find(:all).each do |ds|
{ label: "#{ds.title}", category: "Data Sheets" },
- Brochure.find(:all).each do |br|
{ label: "#{br.title}", category: "Brochures" },
$( "#search" ).catcomplete({
delay: 0,
source: data
});
});
but I get the error undefined local variable or method 'ds' for #<#<Class:0x00000005c95a18>:0x00000005c8d570>
I'm not sure if it's because i'm mixing haml with javascript? is there another way around this? All I have in my view is a text field called search, which works with demo code.
Upvotes: 0
Views: 411
Reputation: 79783
Code inside a filter such as :javascript
isn’t treated as Haml, it’s just s string that gets fed through the filter, so -
and =
don’t work as they do in the rest of Haml. You can use interpolation (i.e. #{...}
blocks) though. In fact that’s what’s causing your error – in "#{ds.title}"
Haml is trying to evaluate the ds
, but not in the context of the block passed to Datasheet.find
.
#{}
blocks can span multiple lines, so you could change your code to something like this:
:javascript
$(function() {
var data = [
#{
(Datasheet.find(:all).map do |ds|
"{ label: \"#{ds.title}\", category: \"Data Sheets\" }"
end +
Brochure.find(:all).map do |br|
"{ label: \"#{br.title}\", category: \"Brochures\" }"
end).join(',')
}
];
$( "#search" ).catcomplete({
delay: 0,
source: data
});
});
Here instead of using each
to iterate over each array we use map
to create a new one, then use +
to add the two arrays together and finally use join(',')
to combine them into a single string which is inserted into the page.
This is a pretty ugly and unwieldy bit of code however. A better solution in this case would be to extract out the code that creates the array into a helper and call the helper from your Haml.
Helpers:
def datasheet_array
Datasheet.find(:all).map do |ds|
"{ label: \"#{ds.title}\", category: \"Data Sheets\" }"
end
end
def brochure_array
Brochure.find(:all).map do |br|
"{ label: \"#{br.title}\", category: \"Brochures\" }"
end
end
def array_for_js
"[#{(datasheet_array + brochure_array).join(',')}]"
end
Then your Haml can be the much clearer:
:javascript
$(function() {
var data = #{array_for_js};
$( "#search" ).catcomplete({
delay: 0,
source: data
});
});
Upvotes: 2