gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
To show off the power of this simple, controller-instance-bound-to-HTML-element concept, let's count how many times each element is clicked and print that inside the element.
Head over to the controller. I'm going to start by inventing a new property called count in connect()
: this.count = 0
.
... lines 1 - 2 | |
export default class extends Controller { | |
connect() { | |
... line 5 | |
this.count = 0; | |
... lines 7 - 11 | |
} | |
} |
That property isn't a stimulus
thing... I'm just creating a property for our own use and initializing it to zero.
Below this, attach a click
listener to our element: this.element.addEventListener()
, click
then a hipster arrow function. Oh, that's mad because I forgot my comma!
Inside, say this.count++
to increment and then this.element.innerHTML = this.count
.
... lines 1 - 3 | |
connect() { | |
... lines 5 - 7 | |
this.element.addEventListener('click', () => { | |
this.count++; | |
this.element.innerHTML = this.count; | |
}); | |
} | |
... lines 13 - 14 |
If you're not super familiar with using the native DOM Element object methods, like addEventListener()
, don't worry! I'm not using jQuery because, in a lot of cases, it's really not needed. But if you're more comfortable with using jQuery, awesome! You can totally still use it! Just install it - yarn add jquery --dev
- then import it into any file that needs it - import $ from 'jquery'
. Oh, and if you're migrating a legacy app where you have jquery already included via a script
tag, that's something we talk about in our Encore tutorial.
Anyways, if you are using jQuery, just use $(this.element)
before you call any methods - like $(this.element).on('click')
. Though, we are going to learn a cooler way to attach event listeners in a few minutes.
Ok: I think this is ready! Move over and refresh. Now... click. Boom! The count increments and prints in the element. And, most importantly, we can see that each element is working independently. This proves that there are two separate objects with two separate count
properties.
This isn't even my favorite part of Stimulus. Down in your browser's inspector, right click on the div around one of our controllers and go to "Edit as HTML". Copy the <div data-controller>
and paste to hack in a new one right above it.
What I'm doing is imitating what happens when HTML is added to the page after it's done loading, like via an Ajax call. This is a classic problem with JavaScript. Suppose you have some jQuery code that attaches a click
event listener to all elements that have some class. Usually, that code runs when the page finishes loading.
Now, what happens if you load new HTML onto the page later via Ajax and the HTML contains an element with that class? Is the event listener automatically attached to it? Nope! It's not... unless you go to the hassle of manually re-calling your function that attaches the event listener.
So: can stimulus handle this? Can it somehow "notice" that a new element with data-controller
was added to the page? The answer is.... yup!
When I click off to add the new element to the page... it works! Behind the scenes Stimulus actually did notice that a new element was added to the page and instantiated a brand new controller object for it. That's incredible! It's a game-changer! I can now write nice controller classes, return HTML via Ajax and not have to worry about re-initializing behavior on that new HTML.
And, of course, the controller works exactly like the other ones: it increments as I click.
If this were the end of Stimulus's features, I'd absolutely use it. But it's not! Let's learn about "targets" next: an easy way to find elements inside of the controller's main element.
Hey Eddie
As a recommendation, try to avoid using global variables, they just add complexity to your code and there are alternatives. If you're doing it using Stimulus, it comes to my mind that you can emit an event whenever an element is clicked, so you can listen to that event and increase the counter. Does it makes sense to you?
Btw, if you don't know how to work with events in Stimulus controllers, this chapter will be of great help https://symfonycasts.com/sc...
Cheers!
Hey Alberto,
Thank you for your interest in this tutorial! The video is already published, pleasant viewing ;)
P.S. More will come soon, usually we're trying to release at least one video a day, but sometimes things go busy, thank you for your patience!
Cheers!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"composer/package-versions-deprecated": "1.11.99.1", // 1.11.99.1
"doctrine/annotations": "^1.0", // 1.11.1
"doctrine/doctrine-bundle": "^2.2", // 2.2.3
"doctrine/doctrine-migrations-bundle": "^3.0", // 3.0.2
"doctrine/orm": "^2.8", // 2.8.1
"phpdocumentor/reflection-docblock": "^5.2", // 5.2.2
"sensio/framework-extra-bundle": "^5.6", // v5.6.1
"symfony/asset": "5.2.*", // v5.2.3
"symfony/console": "5.2.*", // v5.2.3
"symfony/dotenv": "5.2.*", // v5.2.3
"symfony/flex": "^1.3.1", // v1.18.5
"symfony/form": "5.2.*", // v5.2.3
"symfony/framework-bundle": "5.2.*", // v5.2.3
"symfony/property-access": "5.2.*", // v5.2.3
"symfony/property-info": "5.2.*", // v5.2.3
"symfony/proxy-manager-bridge": "5.2.*", // v5.2.3
"symfony/security-bundle": "5.2.*", // v5.2.3
"symfony/serializer": "5.2.*", // v5.2.3
"symfony/twig-bundle": "5.2.*", // v5.2.3
"symfony/ux-chartjs": "^1.1", // v1.2.0
"symfony/validator": "5.2.*", // v5.2.3
"symfony/webpack-encore-bundle": "^1.9", // v1.11.1
"symfony/yaml": "5.2.*", // v5.2.3
"twig/extra-bundle": "^2.12|^3.0", // v3.2.1
"twig/intl-extra": "^3.2", // v3.2.1
"twig/twig": "^2.12|^3.0" // v3.2.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.0
"symfony/debug-bundle": "^5.2", // v5.2.3
"symfony/maker-bundle": "^1.27", // v1.30.0
"symfony/monolog-bundle": "^3.0", // v3.6.0
"symfony/stopwatch": "^5.2", // v5.2.3
"symfony/var-dumper": "^5.2", // v5.2.3
"symfony/web-profiler-bundle": "^5.2" // v5.2.3
}
}
// package.json
{
"devDependencies": {
"@babel/preset-react": "^7.0.0", // 7.12.13
"@popperjs/core": "^2.9.1", // 2.9.1
"@symfony/stimulus-bridge": "^2.0.0", // 2.1.0
"@symfony/ux-chartjs": "file:vendor/symfony/ux-chartjs/Resources/assets", // 1.1.0
"@symfony/webpack-encore": "^1.0.0", // 1.0.4
"bootstrap": "^5.0.0-beta2", // 5.0.0-beta2
"core-js": "^3.0.0", // 3.8.3
"jquery": "^3.6.0", // 3.6.0
"react": "^17.0.1", // 17.0.1
"react-dom": "^17.0.1", // 17.0.1
"regenerator-runtime": "^0.13.2", // 0.13.7
"stimulus": "^2.0.0", // 2.0.0
"stimulus-autocomplete": "^2.0.1-phylor-6095f2a9", // 2.0.1-phylor-6095f2a9
"stimulus-use": "^0.24.0-1", // 0.24.0-1
"sweetalert2": "^10.13.0", // 10.14.0
"webpack-bundle-analyzer": "^4.4.0", // 4.4.0
"webpack-notifier": "^1.6.0" // 1.13.0
}
}
Hello, I have a question. What is the right way to manipulate a global variable? Let's say I have two "click me" elements and 1 counter variable. I want If I click on element 1 or element 2, both elements counters to increment by 1. In this scenario, where should I put the global variable?