Real-World Stimulus Example
Let's put Stimulus to the test. Here's our goal: when we click the play icon, we're going to make an Ajax request to our API endpoint... the one in SongController. This returns the URL to where this song can be played. We'll then use that in JavaScript to... play the song!
Take hello_controller.js and rename it to, how about song-controls_controller.js. Inside, just to see if this is working, in connect(), log a message. The connect() method is called whenever Stimulus sees a new matching element on the page.
| import { Controller } from '@hotwired/stimulus'; | |
| /* | |
| * This is an example Stimulus controller! | |
| * | |
| * Any element with a data-controller="hello" attribute will cause | |
| * this controller to be executed. The name "hello" comes from the filename: | |
| * hello_controller.js -> "hello" | |
| * | |
| * Delete this file or adapt it for your use! | |
| */ | |
| export default class extends Controller { | |
| connect() { | |
| console.log('I just appeared into existence!'); | |
| } | |
| } |
Now, over in the template, hello isn't going to work anymore, so remove that. What I want to do is surround each song row with this controller.... so that's this song-list element. After the class, add {{ stimulus_controller('song-controls') }}.
| {% extends 'base.html.twig' %} | |
| {% block title %}Create a new Record | {{ parent() }}{% endblock %} | |
| {% block body %} | |
| <div class="container"> | |
| // ... lines 7 - 36 | |
| {% for track in tracks %} | |
| <div class="song-list" {{ stimulus_controller('song-controls') }}> | |
| // ... lines 39 - 50 | |
| </div> | |
| {% endfor %} | |
| // ... lines 53 - 55 | |
| </div> | |
| {% endblock %} |
Let's try that! Refresh, check the console and... yes! It hit our code six times! Once for each of these elements. And each element gets its own, separate controller instance.
Adding Stimulus Actions
Okay, next, when we click play, we want to run some code. To do that, we can add an action. It looks like this: on the a tag, add {{ stimulus_action() }} - another shortcut function - and pass this the controller name that you're attaching the action to - song-controls - and then a method inside of that controller that should be called when someone clicks this element. How about play.
| {% extends 'base.html.twig' %} | |
| {% block title %}Create a new Record | {{ parent() }}{% endblock %} | |
| {% block body %} | |
| <div class="container"> | |
| // ... lines 7 - 36 | |
| {% for track in tracks %} | |
| <div class="song-list" {{ stimulus_controller('song-controls') }}> | |
| <div class="d-flex mb-3"> | |
| <a href="#" {{ stimulus_action('song-controls', 'play') }}> | |
| <i class="fas fa-play me-3"></i> | |
| </a> | |
| // ... lines 43 - 49 | |
| </div> | |
| </div> | |
| {% endfor %} | |
| // ... lines 53 - 55 | |
| </div> | |
| {% endblock %} |
Cool huh? Back in song controller, we don't need the connect() method anymore: we don't need to do anything each time we notice another song-list row. But we do need a play() method.
And like with normal event listeners, this will receive an event object... and then we can say event.preventDefault() so that our browser doesn't try to follow the link click. To test, console.log('Playing!').
| import { Controller } from '@hotwired/stimulus'; | |
| // ... lines 2 - 11 | |
| export default class extends Controller { | |
| play(event) { | |
| event.preventDefault(); | |
| console.log('Playing!'); | |
| } | |
| } |
Let's go see what happens! Refresh and... click. It's working. It's that easy to hook up an event listener in Stimulus. Oh, and if you inspect this element... that stimulus_action() function is just a shortcut to add a special data-action attribute that Stimulus understands.
Installing and Importing Axios
Ok, how can we make an Ajax call from inside of the play() method? Well, we could use the built-in fetch() function from JavaScript. But instead, I'm going to install a third-party library called Axios. At your terminal, install it by saying:
yarn add axios --dev
We now know what this does: it downloads this package into our node_modules directory, and adds this line to our package.json file.
Oh, and side note: you absolutely can use jQuery inside of Stimulus. I won't do it, but it works great - and you can install - and import - jQuery like any other package. We talk about that in our Stimulus tutorial.
Ok, so how do we use the axios library? By importing it!
At the top of this file, we're already importing the Controller base class from stimulus. Now import axios from 'axios'. As soon as we do that, Webpack Encore will grab the axios source code and include it in our built JavaScript files.
| // ... lines 1 - 11 | |
| import axios from 'axios'; | |
| // ... lines 13 - 21 |
Now, down here, we can say axios.get() to make a GET request. But... what should we pass for the URL? It needs to be something like /api/songs/5... but how do we know what the "id" is for this row?
Stimulus Values
One of the coolest things about Stimulus is that it allows you to pass values from Twig into your Stimulus controller. To do that, declare which values you want to allow to passed in via a special static property: static values = {}. Inside, let's allow an infoUrl value to be passed. I totally just made up that name: I'm thinking we'll pass in the full URL to the API endpoint. Set this to the type that this will be. So, a String.
We'll learn how we pass this value from Twig into our controller in a minute. But because we have this, below, we can reference the value by saying this.infoUrlValue.
| // ... lines 1 - 11 | |
| import axios from 'axios'; | |
| // ... line 13 | |
| export default class extends Controller { | |
| static values = { | |
| infoUrl: String | |
| } | |
| // ... line 18 | |
| play(event) { | |
| // ... lines 20 - 21 | |
| console.log(this.infoUrlValue); | |
| //axios.get() | |
| } | |
| } |
So how do we pass that in? Back in homepage.html.twig, add a second argument to stimulus_controller(). This is an array of the values you want to pass into the controller. Pass infoUrl set to the URL.
Hmm, but we need to generate that URL. Does that route have a name yet? Nope! Add name: 'api_songs_get_one'.
| // ... lines 3 - 10 | |
| class SongController extends AbstractController | |
| { | |
| ('/api/songs/{id<\d+>}', methods: ['GET'], name: 'api_songs_get_one') | |
| public function getSong(int $id, LoggerInterface $logger): Response | |
| { | |
| // ... lines 16 - 27 | |
| } | |
| } |
Perfect. Copy that... and back in the template, set infoURl to path(), the name of the route... and then an array with any wildcards. Our route has an id wildcard.
In a real app, these tracks would probably each have a database id that we could pass. We don't have that yet... so to, kind of, fake this, I'm going to use loop.index. This is a magic Twig variable: if you're inside of a Twig for loop, you can access the index - like 1, 2, 3, 4 - by using loop.index. So we're going to use this as a fake ID. Oh, and don't forget to say id: then loop.index.
| // ... lines 1 - 4 | |
| {% block body %} | |
| <div class="container"> | |
| // ... lines 7 - 36 | |
| {% for track in tracks %} | |
| <div class="song-list" {{ stimulus_controller('song-controls', { | |
| infoUrl: path('api_songs_get_one', { id: loop.index }) | |
| }) }}> | |
| // ... lines 41 - 52 | |
| </div> | |
| {% endfor %} | |
| // ... lines 55 - 57 | |
| </div> | |
| {% endblock %} |
Testing time! Refresh. The first thing I want you to see is that, when we pass infoUrl as the second argument to stimulus_controller, all that really does is output a very special data attribute that Stimulus knows how to read. That's how you pass a value into a controller.
Click one of the play links and... got it. Every controller object is passed its correct URL!
Making the Ajax Call
Let's celebrate by making the Ajax call! Do it with axios.get(this.infoUrlValue) - yes, I just typo'ed that, .then() and a callback using an arrow function that will receive a response argument. This will be called when the Ajax call finishes. Log the response to start. Oh, and fix to use this.infoUrlValue.
| import { Controller } from '@hotwired/stimulus'; | |
| // ... lines 3 - 11 | |
| import axios from 'axios'; | |
| // ... line 13 | |
| export default class extends Controller { | |
| // ... lines 15 - 18 | |
| play(event) { | |
| event.preventDefault(); | |
| axios.get(this.infoUrlValue) | |
| .then((response) => { | |
| console.log(response); | |
| }); | |
| } | |
| } |
Alrighty, refresh... then click a play link! Yes! It dumped the response... and one of its keys is data... which contains the url!
Time for our victory lap! Back in the function, we can play that audio by creating a new Audio object - this is just a normal JavaScript object - passing it response.data.url... and then calling play() on this.
| import { Controller } from '@hotwired/stimulus'; | |
| // ... lines 2 - 11 | |
| import axios from 'axios'; | |
| export default class extends Controller { | |
| // ... lines 15 - 18 | |
| play(event) { | |
| event.preventDefault(); | |
| axios.get(this.infoUrlValue) | |
| .then((response) => { | |
| const audio = new Audio(response.data.url); | |
| audio.play(); | |
| }); | |
| } | |
| } |
And now... when we hit play... finally! Music to my ears.
If you want to learn more about Stimulus - this was a bit fast - we have an entire tutorial about it... and it's great.
To finish off this tutorial, let's install one more JavaScript library. This one will instantly make our app feel like a single page app. That's next.
45 Comments
You're welcome ;)
What is this "infoUrlValue?" and why we have to use that instead of "infoUrl"
Hey Appketo,
That is "Stimulus Values" concept. Please, rewatch this video one more time if you didn't get it. But in short, you are able to pass some values from the template to the Stimulus controller via something called "values". But to get a passed Stimulus Value you need to add the "Value" prefix to it, e.g. like in this case with infoUrlValue, i.e. this.infoUrlValue.
So, you just need to get used to this "Stimulus syntax", it's standartized thing by it.
I hope it clarifies things a bit more for you!
Cheers!
Okay, thank you for the explanation. So something like this https://stimulus.hotwired.d...
Hey Appketo,
Yes, exactly. Looks like you found this feature described in docs, good catch!
Cheers!
Good old rickroll, and that was loud as well! :D I'm not sure if it's been reported before or not, but there is an issue with pasting text into this input field, it adds empty rows. With each paste it gets progressively worse. Something to keep in mind.
Great stuff so far, although throughout this course I've been screaming at my monitor: "Where are Models? Surely they're coming any moment now...". Also, as someone who has a background in Laravel, are there Request Validation classes in Symfony? Regex in the middle of URL path seems very unreadable in my opinion.
Hey Filip,
> Good old rickroll, and that was loud as well! :D I'm not sure if it's been reported before or not, but there is an issue with pasting text into this input field, it adds empty rows. With each paste it gets progressively worse. Something to keep in mind.
I think I know what exactly you're talking about... if you're talking about Disqus comment field - yes, that's a known bug in Disqus, not sure why it's not fixed yet... but so far it's only problem for Firefox - the browser you're using I suppose? :) Try it in Chrome - no new lines should be added ;) Anyway, nothing much we can do with that unfortunately... though we're not happy with Disqus comments system too, so we're going to replace it with a custom one some day, but still no specific release date. Thanks for you patience and understanding!
Unfortunately, I'm not familiar with Laravel Request Validation... but I think you can find some answers in docs: https://symfony.com/doc/cur...
I hope this helps!
Cheers!
Yo Filip Jakovljevic!
And... to add some more:
> "Where are Models??
Are you referring to "database models"? If so, we do them (will do them) in the 3rd course of this series. I know you need them to build anything real, but we keep them "away" so we can focus on some "fundamentals". But yes, they're coming :).
> As someone who has a background in Laravel, are there Request Validation classes in Symfony? Regex in the middle of URL path seems very unreadable in my opinion
They're... sort of 2 different things. In this tutorial, we're talking about making a route simply NOT match unless the "wildcard" is a digit. It's not quite "validation". There IS a separate validation system - it's quite different than Laravel, but would feel much more familiar. Btw, this is the regex version that Laravel uses for what we did: https://laravel.com/docs/9.... - it's not in the route, but it's still regex.
And actually, on this last point, Symfony 6.1 has a nice feature for common regex requirements: some built-in regex via constants - https://symfony.com/blog/ne... (btw, that post also shows how you can put requirements as an option, instead of sticking them right INSIDE of the route string itself).
Cheers - we appreciate the comments and questions!
Thank you guys for replying. As for the Firefox bug, I am indeed on Firefox and it doesn't bother me at all. It just seemed like something that could easily slip under the cracks and I've wanted to report it in case it wasn't already, but since it was no worries about that. :)
Here's what I was referring to by Request Validation classes. Inside of this class there is a rules method where we can store all of our rules, i.e. required, numeric, and so on. There is also another method called failedValidation where you can customize the response for any scenario you'd like, in this case we could throw a 4xx and an appropriate JSON response. Yup, I am primarily talking from a standpoint of someone who is building a RESTful API so a 404 page wouldn't work for me, but even if I wasn't, that's how I would approach this. This method also avoids regex entirely, in or outside of the route. Is the validation system similar to this?
As for the Models, I'm referring to them as a part of the MVC structure. I guess that you guys call them Entities? The "database models" can be a bit misleading since they don't have to actually interact with the DB, as far as I know, although they're very useful when it comes to doing so.
To make things simpler, I am applying for a junior developer position. I have been given a task to do in Symfony and am looking at how to approach it. I need to make a small game/program where you can type a word and get points for it. The word needs to be an actual word, they get 1 point for each letter, 3 extra points if the word is a palindrome and 2 if it's almost a palindrome. I'd obviously have a view where user can type in their word, an API route towards the controller, and from the controller I'd make a Word object to validate the word. I understand the way views and controllers work, and while I could place the entire points system directly inside of a controller that's not the MVC way and that's pretty much how I've been taught to program. Would such logic belong inside of an Entity?
Sorry for the long reply, I hope that this could be useful to some other people in the future as well.
Hey Filip J. !
Sorry for the slow reply!
Ah, I see! Symfony doesn't have anything that's quite like this. Or, more accurately, this is done differently in Symfony :). Let me explain it in two parts:
A) First, the regex we used in the route - even in Laravel - I would STILL use route requirements for this. And I think I didn't really show this off correctly in the tutorial. This is because the MAIN purpose of that regex is not "validation" but to make it so that the route doesn't match... which is only really needed if you have 2 routes whose URLs are very similar. For example:
See the problem? :). Both match the same pattern! This is the main use-case for adding the regex: make
pageonly match "digits"... and then if you go to/articles/foothat will NOT match the first route, but will fall down and match the second. So, not really validation, just a trick to make two very-similar routes match. I believe you would solve this in Laravel the same way.However, with argument types (e.g. the
intbefore the$page) argument, if you choose to use these, then these requirements have a second purpose (which is what I was showing in the tutorial): to make sure that going to/articles/foodoes NOT match the first route... so that Symfony doesn't try to pass the stringfooto theint $pageargument. I suppose this is a type of validation, though mostly when we talk about validation, we're talking about validating a bunch of data (either POST or JSON data) that's sent on the request (which I think is the main purpose of those request validation classes in Laravel also).B) Ok, so how DOES Symfony do validation, specifically for an API? You can do various levels of complexity, but we would typically do this:
i) Create a class (maybe it is a Doctrine entity class) with all of the fields in your API. For example, suppose we have an
Articleentity with some fields liketitleandbody.ii) Use Symfony's serializer to "deserialize" the incoming JSON into a new instance of
Article. So now, that object is populated with the incoming data. It may, at this moment, be in an "invalid" state.iii) Add validation constraints above the properties in your
Articleclass, like#[Assert\NotBlank].iv) Use Symfony's validator to validate the
Articleobject itself. This will return aConstraintViolationList(fancy object that holds an array of "violations").v) Transform this into JSON. You could do this by hand, or you could once again use Symfony's serialize to serialize the
ConstraintViolationListinto JSON.API Platform is a great platform that has a lot of this built-in. But ultimately, this is what it's doing behind the scenes :).
Btw, if the user goes to
/api/songs/foo, then you actually DO want to trigger a 404. But you're right, you don't want a 404 "page", but rather a 404 JSON response. If you're using my requirements trick, then Symfony will trigger the "404" for you before the controller is called. But you can "hint" to Symfony that this request is a "json" request, and that it should return the 404 error as JSON and not HTML. This is not as easy as it should be, I'll admit. You need to set this little_formatthing - here's an example - https://stackoverflow.com/questions/12442827/how-can-i-tell-symfony2-to-always-use-format-json-for-a-certain-url-pattern#answers - if your entire site is an API, this is pretty easy to do - I'd add thatdefaults: { _format: 'json' }to the route import for thesrc/Controllers/directory. You'll find this inconfig/routes/annotations.yamlorconfig/routes.yamldepending on your Symfony version.The idea is kind of cool: you throw errors (like 404 errors) just like you would in an HTML application. Then Symfony returns an HTML or JSON version based on the "format" of the request. If you want to further customize what the 404 JSON looks like, you can: https://symfony.com/doc/current/controller/error_pages.html#overriding-error-output-for-non-html-formats
Correct! We usually call these "entities"... but as far as MVC goes, you're right that "models" means something bigger. So, if you want to talk to the database, those are "Doctrine entities" and we'll get to those. Beyond that, "models" is often also used to refer to "services" (we'll create our own services in the next tutorial) and "simple data-hold objects that are not Doctrine entities", which you create ad-hoc in your app if/when you find yourself passing around some array of data.. which would be more organized in a class. So as usual, the "M" in MVC is where your business logic goes, so it's largely up to you to build what you need. In Symfony, we rely heavily on "services" in this M layer.
Ah, cool! I'd clarify if they want an API endpoint or not. This can also be built with Symfony's form component. Just two different approaches.
If you have time, I'd watch our "Symfony 5 Fundamentals" tutorial - specifically the parts about services. Services are classes that "do work". So, if you find that you have a bunch of "work" being done in a controller (like calculating a score), then that is a good candidate to pull out into a service - e.g. a
WordScorerservice, which has a public function where you can pass it the "submitted word" and it returns the integer score. In this case, you may or may not need aWordclass... just because... what would it hold beyond the string "word" that was submitted? Put the scoring logic into a "service" - that's the "Symfony" way :).Cheers!
I am experiencing some strange behavior.
I am using Symfony 6.3 and have both required the encore bundle (v2.1.1) and stimulus bundle (v2.12.0) separately. I have installed all dependencies via composer and npm. When I run
npm run watchI see no errors. When I kept the default connect textContent behavior which came with the recipe I could see a sample div get the text loaded from JS. Whenever I try toconsole.logsomething though, nothing appears in the console. I thought it could be some problem with the console.log so I continued watching the video. When I got to theplaypart, when I click a link, I get redirected to a "/#" URL which means theevent.preventDefault()doesn't work. I have followed everything closely and copied everything from the scripts. Yet it still doesn't work. The only thing that works is the initial sample code after installing the package. When I check mypublic/build/app.jsmy modified code is there and should be working.Does anyone have a clue what's happening?
Hey @Petar
When you make changes, do you get any errors from the
npm run watchcommand? I wonder if Webpack is failing to build. Another possibility is the cache is not being cleared. Try hard-refreshing your browser.Cheers!
Hi @MolloKhan
There were no errors whenever I changed the code so the build was successful.
I played around again and found what the problem was though. At first I didn't know that the
stimulus_controllershould be kept in the parent element so I was running onlystilumus_actionalone in my twig file withoutstimulus_controller. Once I addedstimulus_controllerin the parent element it worked.Does this mean that everytime when I want to run a JS method I need to use both
stimulus_controllerandstimulus_action?Sorry for my slow reply, a long weekend got in the middle.
You are not forced to use a
stimulus_actionwhenever you need to do something after a specific event (on click, key stroke, etc.), you can create your own event listeners, but I recommend sticking withstimulus_actionsCheers!
Hello,
I have a problem with 1:10 part.
<div class="song-list" {{stimulus_controller('song-controls')}}> - it doesn't work at all, however I have changed the title of the file to song-controls_controller.js
Strange that when I change it into old origin controller name "hello"
<div class="song-list" {{stimulus_controller('hello')}}> - it is working in old style showing "Hello Stimulus! Edit me in assets/controllers/hello_controller.js"
Why Stimulus remembers the old controller and does not accept the new one?
Hey @Marcin-K
I believe it is a cache thing. Try a hard-refresh on your browser
Cheers!
Hi @MolloKhan @Aymen
I have tried cache clearing
php bin/console cache:clear- but did not work. Cookies deleting also :(I have started
npm run watchand I saw another problem - error in ./assets/controllers.jsonError: The file "@symfony/ux-turbo/package.json" could not be found.
Installed
composer require symfony/ux-turboandnpm install --force- does not help.How get this turbo package.json?
Oh, so the reason that you were saying the old code is because Webpack is failing. That error is unexpected though. Let me see what you have in your
assets/controllers.jsonfile, also I'd like to see yourcomposer.jsonandpackage.jsonfile. Besides that, you could try reinstalling your vendors (composer and npm)@MolloKhan
I am on the road again! :D
It was the problem with an old version of Composer and NPM.
composer self-updateandnpm updatemade the work.npm run watchis compiling.Thanks man for your help, you're the best!
Awesome news, keep it up @Marcin-K !
Hey,
Have you tried clearing your php cache ?
php bin/console cache:clearIt worked for me when I did that, but I am not used to the chrome developer tools so I don't know why my console looks like this :
Note that I used song-controls but wanted to try as you said with the old name; I get the same result
instead of only :
Hey @Aymen
It seems like it is instantiating many
hello_controller.jsobjects. If you add a console log to theconnect()method, do you see that log many times or only once?Hi! What if you make certificate achievements per Track? I think it would be more valuable to share such an award in profiles.
Hey @vshandak,
That sounds interesting - I'll share it with the team
Thanks for the idea. Cheers!
Hello!
I have a problem with {{ stimulus_controller('song-controls') }} function, I get an error: "Unknown "stimulus_controller" function.".
When I add it like data-controller="song-controls" it works.
Can you help me with this problem?
Hey @Ahmed-M,
Can you check please what version of
symfony/webpack-encore-bundledo you have installed?Cheers!
It is: "symfony/webpack-encore-bundle": "^2.0"
ok, now I see
I think the easiest way to fix it will be to run
composer require symfony/stimulus-bundlethat should help
Cheers!
That helped, thank you :)
Hello, first things first : thanks for this nice tutorial series.
But at this point I do have a little problem : I'm not getting my victory lap but a 404 crash... I deserve me too to be rick rolled ! :-D
My AJAX request is not going right : the play method/Action receives from the event listener what seems to be "/this.infoUrlValue/." instead of catching my 'data-song-controls-info-url-value' well sent. My Symfony is trying to get "https://127.0.0.1:8000/this.infoUrlValue", so I do get an error via the Firefox network inspector like "Uncaught (in promise)
Object { stack: "AxiosError@https://127.0.0.1:8000/build/vendors-node_modules_symfony_stimulus-bridge_dist_index_js-node_modules_core-js_modules_es_da-81f073.js:7868:19\nsettle" and much more..
Is Axios the problem ? Does it fail to "bridge" the request?
Hey @NickNem
That's a bit weird. How are you making the AJAX request? It seems to me that you're using the
this.infoUrlValuevariable as a stringCheers!
Hi @MolloKhan
Yup, as I'm getting it : I'm doing my AJAX request within the play method, who's awaiting for his event -listener- object via 'axios.get(this.infoUrlValue)'...and sent as a string (!) infoUrl like declared in the static values property inside the export default class from the song-controls_controller.
My framework-bundle distribution is 6.2.8
Ok, so your JS code seems to be correct. How are you sending the
infoUrlvalue to the Stimulus controller?I double² checked, compared with the downloadable code given, everythings seems right to me
¯\(ツ)/¯
homepage.html.twig
<div class="song-list" {{ stimulus_controller('song-controls', {infoUrl: path('api_songs_get_one', { id: loop.index }) }) }}>
SongController.php
#[Route('/api/songs/{id<\d+>}', methods: ['GET'], name: 'api_songs_get_one')]
Like I said in mee precedent post, the only thing I'm able to catch is the fact that I'm not with the same distribution that the tutorial is made (6.0 vs 6.2), thanks @MolloKhan I'm going for another attentive look to the thing this afternoon to catch the bug :-)
That's very odd. I don't think the version is causing this error. What do you see if you dump the
this.infoUrlValuebefore and after the AXIOS call?@MolloKhan thanks, I'm back at it, I'll do the var dump, I think I'll take another fresh start, I don't want to flood the discussion with noobie gibberish, It could take some time, I'm missing some points for sure, just for an example I saw that I had some Php extensions that were missing (-‸ლ) , I hope I'll get back to this to tell what was my problem if I'm able to reproduce it and to nail it
hi, thanks for the course, is very good to begin with SF6 now good, i have one question
when installing "yarn add bootstrap --dev" there is a detail with "popperjs" dependency.
this occurs because the project "popperjs" now is "floatin UI", so i do not can integrate the reference
Hey Andri-C,
Hm, do you mean you cannot install
@floating-ui/dompackage because it conflicts with bootstrap and popperjs? I just tried to runyarn add @floating-ui/dom --devand it was installed into my project without problems though I have Bootstrap installed. Could you elaborate more on this? What command exactly are you trying to execute? What error exactly do you see?Cheers!
Hi
I've just added and set up stimulus in one of my test applications. The speed increase is awesome however all my old jquery code stops working unless I hit refresh.
Do I need to move it all to a stimulus controller or is there a way to get it working?
Thank you
Steve
Hey Steve-D,
Ah, that might be tricky :) Ideally, rewrite all your JS code with Stimulus :p But if it requires a lot of time and you cannot do it right now - you can try to fix it. And it also depends if the problem in your custom JS code or in the JS code of a library you're using. The 2nd would be much harder to fix, and probably the best option is to switch to another similar JS library that can give you the same features but also works well with Stimulus.
But if the problem in your code - it might be easier to fix it. In theory, you just need to find elements in a different way stating finding them outside of the Stimulus code, .e.g if you replace some HTML with Stimulus, then outer HTML tag as a base jQuery tag, and then search required element from it, i.e.
$('#out-of-stimulus-element').find('.something-inside-of-stimulus-element'). This way, no matter if the.something-inside-of-stimulus-elementelement will be replaced by Stimulus or not - you will always be able to find it this way.Same way for any listeners you have. Actually, jQuery listeners already support this, all you need to do is to pass 3 arguments to the
on()instead of 2, e.g.:$('body').on('click', '#out-of-stimulus-element', '.something-inside-of-stimulus-element'). Read more about it here: https://api.jquery.com/on/I hope these tips help! But basically, yeah, there's no easy option you need to activate that will make things work for you - you need to debug your code yourself and find problematic places, then figure out why they do not work and fix them, i.e. rewrite them in a way that will work with Stimulus using some tricks I mentioned above.
Cheers!
Hi Victor
I suspected it might be a case of rewriting the code in Stimulus. I'm going to press on with the tutorial, I'm only at the beginning so need to understand more about Stimulus and Turbo before attempting anything but thank you so much for the detailed response.
Steve
Hey Steve-D,
Sure, yeah, give the tutorial a try till the end, I bet things will become clearer for you at the end.
Cheers!
Hi, How can I disable debug mode for stimulus?
In app.js I added :
import {app} from "./bootstrap";
app.debug = false;
OR
in bootstrap.js :
app.debug = false;
Is it correct way?
Thank you.
Hey Ruslan
I think that's the only way to deactivate it without running your app in production mode (env var: APP_ENV=prod)
Cheers!
"Houston: no signs of life"
Start the conversation!