It looks like if it doesn't exist, it would send the values over to the app. But, likely, it would just send the Value back to the server. From here, we could separate values from integer and strings and create the new categories. This can be nice too since we can limit who can make these changes.
def ajax_locations if params[:q].present? @locations = Location.where('municipality iLIKE :q OR state iLIKE :q OR local_code iLIKE :q OR name iLIKE :q OR country iLIKE :q', q: "%#{ params[:q] }%") render json: @locations.map { |loc| { value: loc.id, text: loc.name } } else render json: [] end skip_authorization end
slimselect_controller.js
connect() { let url_val = this.urlValue new SlimSelect({ select: this.element, searchingText: "Searching...", ajax: function (search, callback) { if (search.length < 3) { callback('need 3 characters to search') return }
let url = new URL(url_val) url.search = new URLSearchParams({ q: search }) console.log(`url: ${ url }`)
I'm not getting any console errors, and I can manually render the url in a separate window and see the result. Example: http://localhost:3000/ajax_locations.json?q=reno
However, nothing happens in the view...no options are added to the select input. Can anyone see where I may have gone wrong?
EDIT: the problem was the initial value being set in the select. By setting the select f.select [], {} it now works. So, now I need to figure out how to set/select an initial value (like on edit).
Hi Dave - I'm still unsuccessful in rendering a slim-select menu with options loaded from Ajax, where an initial value is selected. I have a field that auto-populates based on the users input selection from their previous record. So, the slim-select will load pre-selected to their last saved selected, with the option to search for a different selection. This is tough. It seems doable, but I haven't figured out the secret sauce, yet. In your travels with slim-select did you see/learn anything to pull this off?
I find that adding the option and marking it "selected" in the view actually blocks slim-select from loading options from Ajax. I'm not sure why, you'd think the new Ajax call would over write the existing select options, but instead it chokes...and nothing happens in the view.
Thanks! I'll post back if I find a solution to this.
☒ That was my findings as well. It is rather annoying. I wasn't able to find a suitable solution except to just display what is selected.
If you don't change the value of the select then it will not change the persisted value. But since we are not pre-populating the list, it will allow you to select from the ajax list. I agree, it is rather annoying. I would see this as a defect in slim-select as the same behavior doesn't happen with their multiple select.
If anyone experiences the issue I posted...follow along here https://github.com/brianvoe/slim-select/issues/276. Some good info, and a few ideas. Downgrading to 1.26.1 worked for a few people. The gem seems to be in maintenance limbo at the moment.
Hi Dave! Thanks for the episode. Super clear and helpful as usual! I did something really similar as the example for an app I am coding. It works perfectly in local host. However, when I push to Heroku, looks like the slim select.css is never imported.
In local:
On Heroku:
I tried to move the line import "slim-select/dist/slimselect.css" from the stimulus controller to the app.js and to the app.scss with no result. I have no error thrown in the console.
Hello, I'm trying to use this in Rails 7 with importmaps, I've replaced stimulus with hotwired stimulus and it runs fine but I'm unable to import slim select stylesheet.
If I keep
import "slim-select/dist/slimselect.css"
in stimulus controller I receive following javascript error in console
Uncaught Error: Unable to resolve specifier 'slim-select/dist/slimselect.css' from http://0.0.0.0:3000/...
I have only limited knowledge with stimulus and importams, but the slim-select itself is pinned and I have slim-select package in node_modules, so what I'm doing wrong?
I think that this is where importmaps adds a bit of confusion. It's only going to pin the javascript assets and won't include the CSS bits of the library. Have you tried adding CSSbundling to import in the CSS assets?
That explains a lot of my confusion, I started digging and I'm using cssbundling-rails with tailwind, so I have tailwind.application.css, what I understood is I can't use import in tailwind.application.css and I should use tailwind in postcss or set a separate preprocessor altogether.
So I have tried to install css:install:postcss rename my application.postcss.css to somethingelse.postcss.css my stylesheet link also requires my "somethingelse" in package.json I have updated build:css command to include both preprocessorlike this
Well it will compile both files, and both files are also included in the page, but the import statements are not working (in somethingelse.postcss.css @import "slim-select/dist/slimselect.css"; resolves to nothing) and also my now my profile which contains
css: yarn build:css --watch
is unable to actually watch any of the files, I have to build css manually.
This is so confusing, the rails docs are missing documentation on this subject I have little to no idea what I should do.
This is in part why I prefer esbuild via jsbundling-rails over importmaps. It seems like it brings the familiarity of the asset pipeline (either via sprockets or propshaft) and what we've become accustomed to with Webpacker, but without all of the headaches.
I understand that decision. Anyway, if anyone else runs into these issues, the solution is to use tailwindcss command with --postcss argument, then if postcss-import package is installed import commands starts working correctly and slim-select is resolved and bundled.
Hello. If I want to show all categories (about 5 in list with scrolling) with search, so what I should add to controller? In multiple select. smth like this:
13:16:32 js.1 | The path "./dist/slimselect.css" is not exported by package
2) In case of multiple select I get the following error:
undefined local variable or method `group' for #<ActionView::Base:0x00000000028e60>
group.decks.map { |c| [c.name, c.id] }, {},
^^^^^
Did you mean? group_url
rafal.siepak You may want to try and put the css imports in the CSS file. For example, using bootstrap with css-bundling, if I put the @use in the top of the file, it works.
I have made it work by putting directly @import "slim-select/dist/slimselect.css" into application.tailwind.css.
Another question I have is I want to render html under index page, but right now after applying the code I only render json. How to make both work HTML and json?
class CategoriesController < ApplicationController def index @categories = Category.where("name like ?", "%#{params[:query]}%") render json: @categories.map { |c| { value: c.id, text: c.name } } end end
rafal.siepak It's hard to troubleshoot without more information. But if I had to guess, the logs would probably look something like this.
Processing by CategoriesController#index as */*
Parameters: {"query"=>"something"}
No template found for CategoriesController#index, rendering head :no_content
If that is the case, then the code for the format.json will not get picked up. You should update your URL in the view where you're passing in the URL into the stimulus controller with the json format. Something like this should work.
'select-url-value': categories_url(format: :json)
By doing that, it should then respond with the proper format.
The "Options" and "Methods" selections are particularly useful, but for some reason direct links to those pages don't seem to work.
As a bonus, how would you implement the "addable" function into our Rails app (create tag if doesn't exist yet)?
the view
[@existing_location&.name],
{ },
class: "form-control select",
data: { controller: 'slimselect', 'slimselect-url-value': ajax_locations_url } %>
locations_controller
if params[:q].present?
@locations = Location.where('municipality iLIKE :q OR state iLIKE :q OR local_code iLIKE :q OR name iLIKE :q OR country iLIKE :q', q: "%#{ params[:q] }%")
render json: @locations.map { |loc| { value: loc.id, text: loc.name } }
else
render json: []
end
skip_authorization
end
slimselect_controller.js
let url_val = this.urlValue
new SlimSelect({
select: this.element,
searchingText: "Searching...",
ajax: function (search, callback) {
if (search.length < 3) {
callback('need 3 characters to search')
return
}
let url = new URL(url_val)
url.search = new URLSearchParams({ q: search })
console.log(`url: ${ url }`)
fetch(url)
.then(response => response.json())
.then(json => callback(json))
.catch(error => callback(error))
}
})
}
I'm not getting any console errors, and I can manually render the url in a separate window and see the result. Example: http://localhost:3000/ajax_locations.json?q=reno
EDIT: the problem was the initial value being set in the select. By setting the select f.select [], {} it now works. So, now I need to figure out how to set/select an initial value (like on edit).
Thanks so much!
I find that adding the option and marking it "selected" in the view actually blocks slim-select from loading options from Ajax. I'm not sure why, you'd think the new Ajax call would over write the existing select options, but instead it chokes...and nothing happens in the view.
Thanks! I'll post back if I find a solution to this.
If you don't change the value of the select then it will not change the persisted value. But since we are not pre-populating the list, it will allow you to select from the ajax list. I agree, it is rather annoying. I would see this as a defect in slim-select as the same behavior doesn't happen with their multiple select.
Thanks for the episode. Super clear and helpful as usual!
I did something really similar as the example for an app I am coding. It works perfectly in local host.
However, when I push to Heroku, looks like the slim select.css is never imported.
In local:
On Heroku:
I tried to move the line import "slim-select/dist/slimselect.css" from the stimulus controller to the app.js and to the app.scss with no result. I have no error thrown in the console.
Any idea?
Thanks for your help!
Oops, I didn't. Only had:
<%= stylesheet_link_tag 'application',
media: 'all',
'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application',
'data-turbolinks-track': 'reload',
defer: true %>
Added the line <%= stylesheet_pack_tag 'application' %> and now it works.
Thank you very much for your help
Thank you for your help
in package.json I have updated build:css command to include both preprocessorlike this
Well it will compile both files, and both files are also included in the page, but the import statements are not working (in somethingelse.postcss.css @import "slim-select/dist/slimselect.css"; resolves to nothing) and also my now my profile which contains
This is so confusing, the rails docs are missing documentation on this subject I have little to no idea what I should do.
Anyway, if anyone else runs into these issues, the solution is to use tailwindcss command with --postcss argument, then if postcss-import package is installed import commands starts working correctly and slim-select is resolved and bundled.
I have encountered two issues:
1) I get the following error with css:
[ERROR] Could not resolve "slim-select/dist/slimselect.css"
2) In case of multiple select I get the following error:
Could you help here? Thank you.
Another question I have is I want to render html under index page, but right now after applying the code I only render json. How to make both work HTML and json?
class CategoriesController < ApplicationController
def index
@categories = Category.where("name like ?", "%#{params[:query]}%")
render json: @categories.map { |c| { value: c.id, text: c.name } }
end
end
def index
@decks = Deck.all
respond_to do |format|
format.html
format.json {
@decks = Deck.where("name ILIKE ?", "%#{params[:query]}%")
render json: @decks.map { |c| { value: c.id, text: c.name } }}
end
end
If that is the case, then the code for the format.json will not get picked up. You should update your URL in the view where you're passing in the URL into the stimulus controller with the json format. Something like this should work.
By doing that, it should then respond with the proper format.
1) in Terminal
2) Add css (3 variants)
- add to app/views/layouts/application.html.erb
- in rails console
- add to app/assets/stylesheets/application.css