<p>Keep in mind Craft parses the html of your field, it won't be used directly, thus the ID of your field can't be <code>"#"+startDateFieldHandle</code>unless you ignored Crafts methods or modified it in another way. Your fields ID will be more like</p>

<pre><code>id="fields-{{the id you specified}}"
</code></pre>

<p>Thus you should make sure you used the correct selector like</p>

<pre><code>jQuery("#fields-"+startDateFieldHandle)
</code></pre>

<p>usually your order should be fine.. If you want to pass certain variables to Javascript you should do that in Twig because <code>Craft::$app-&gt;View-&gt;registerJs($js);</code> won't pass variables in a global scope (you can't access them in your JS files in certain cases).</p>

<p>However you should avoid using those globals in Craft. It's better to create a custom <code>Garnish</code> object for the logic</p>

<pre><code>Craft::$app-&gt;getView()-&gt;registerJs('new Garnish.MyAwesomeField(id, options)');
</code></pre>

<p>That will make sure everything is initialized and ready to use
Your js could look like this</p>

<pre><code>Garnish.MyAwesomeField = Garnish.Base.extend(
    {
        $theOtherField: null,
        $field: null,
        options: {},
        init: function (fieldId, settings) {
            this.options = $.extend({}, Garnish.MyAwesomeField.defaults, settings);
            this.$theOtherField = $('#' + this.options.fieldSelector + this.options.theOtherFieldHandle);
            this.$field = $('#' + this.options.fieldSelector + fieldId);
            this.addListener(this.$field, 'click', $.proxy(this, 'clickEvent'));
        },
        clickEvent: function(){
            alert( this.$theOtherField.val() );

        }
    },
    {
        defaults:{
            fieldSelector: 'fields-',
            otherFieldHandle: ''
        }
    }
);
</code></pre>

CC BY-SA 4.0
2018-05-28T13:04:27.423Z
Sorry, I got pulled away a few days. Thank you so much, Robin, for the time and care you put into answering this question. I really appreciate it!
kr37
CC BY-SA 4.0
2018-05-28T14:54:03.403Z
I'm trying to wrap my head around this Garnish object. My custom "field" is a button that posts to a controller which sends back some mini-ajax-calendars for inserting and deleting events from the calendar.
kr37
CC BY-SA 4.0
2018-05-28T15:03:09.330Z
So this garnish object gives a place to keep some information, and it should be updated correctly, and it also can provide a listener for the the click event? And in the php preceding this, I set `$theOtherField = 'startDateField'`
kr37
CC BY-SA 4.0
2018-05-28T15:23:53.317Z
"o this garnish object gives a place to keep some information, and it should be updated correctly, and it also can provide a listener for the the click event?" -> yes.... You can insert all needed options via PHP and pass it to the object like in my example. `options` will be an array of your settings like the other field handle or whatever you need
Robin Schambach
CC BY-SA 4.0
2018-05-28T15:50:57.663Z
In your garnish.js, you use `this.$field`. Why not hardcode this as `this.fieldId` ?
kr37
CC BY-SA 4.0
2018-05-28T20:03:35.383Z
Because you need the actual html element in order to bind events
Robin Schambach
CC BY-SA 4.0
2018-06-09T15:21:32.870Z
I'm really slow at this. The `Garnish.MyAwesomeField = Garnish.Base.extend...` stuff goes in my `src/resources/occurrencesField.js` which is where the button click js lived, and all that button-click js just goes inside the skeleton clickEvent you provided?
kr37
CC BY-SA 4.0
2018-06-09T15:33:32.973Z
You can place the files wherever you like. There are no restrictions. I'm not sure what a `button-click` js is. You'll need to attach an accessible function as event listener to your button. The most elegant way to do this on global level is within a garnish class like I showed. It doesn't matter where that garnish class is or where it comes from. This is actually the only about js scopes and how you should always use Javascript - not really about Craft
Robin Schambach
CC BY-SA 4.0
2018-06-12T18:21:26.240Z
Yes, it's been almost 3 years since I've done any javascript, and wrapping my mind around the interplay between php and javascript has taken me a while to remember. Thank you so much for all the help! This part is more or less working. Now on to the controller!
kr37
CC BY-SA 4.0
2018-05-24T07:20:41.410Z
2018-05-24T07:32:58.583Z
2018-05-24T07:32:58.583Z
Robin Schambach
<p>Updating a plugin from Craft 2 to Craft 3, so this logic used to work.</p>

<p>The plugin has a field-type which is a button. When clicked, the button does stuff depending upon another field. That handle(ID) of that other field must be passed to the button's javascript.</p>

<p>The field's class seems to register the js correctly. When the page loads, it gives a popup with the correct info.</p>

<pre><code>var startDateFieldHandle = 'fields-startDate';
alert( 'startDateFieldHandle = '+startDateFieldHandle);
</code></pre>

<p>Above that is
<code>&lt;script src="http://f.dev/cpresources/6991e452/occurrencesField.js?v=1527142206"&gt;&lt;/script&gt;</code>
which pulls in the following:</p>

<pre><code>jQuery(document).ready(function(){
    $("#fields-cal37_choose_dates_button").click( function() { 
        alert('Clicked the button');
...
        var start_date = new Date( jQuery("#"+startDateFieldHandle).val() );
</code></pre>

<p>The alerts happen in the correct sequence, but nevertheless my guess is that because <code>&lt;script cpresources&gt;</code> bit occurs earlier on the page than where <code>startDateFieldHandle</code> is set, that somehow it still isn't set when the button is clicked.</p>

<p>I don't see, using <code>Craft::$app-&gt;View-&gt;registerJs($js);</code> that there is any way to say "put this first."  </p>

<p>It did used to work under Craft 2. Any tips? </p>

<p><strong>Update</strong><br>
At present, I'm seeing in <code>occurrencesField.js</code> that as soon as I reference the startDateFieldHandle variable in any way, such as <code>alert(startDateFieldHandle);</code> the script quits.</p>

<p>Also, in the Firefox console, I'm getting:</p>

<pre><code>jQuery.Deferred exception: startDateFieldHandle is not defined @http://f.test/cpresources/6d6f7137/occurrencesField.js?v=1527518592:101:2
l/&lt;/e@http://f.test/cpresources/61c13c0c/jquery.js?v=1527049453:1:29794
l/&lt;/t&lt;@http://f.test/cpresources/61c13c0c/jquery.js?v=1527049453:1:30109
 undefined  jquery.js:1:31365
Double-instantiating a menu button on an element garnish.js:1:2512
</code></pre>

<plugin-development><javascript><custom-fieldtype><garnish>
Plugin field-type not getting javascript variable?
# Plugin field-type not getting javascript variable?

(Asked by: username_0 on 2018-05-24)

Updating a plugin from Craft 2 to Craft 3, so this logic used to work.
The plugin has a field-type which is a button. When clicked, the button does stuff depending upon another field. That handle(ID) of that other field must be passed to the button's javascript.
The field's class seems to register the js correctly. When the page loads, it gives a popup with the correct info.
var startDateFieldHandle = 'fields-startDate';
alert( 'startDateFieldHandle = '+startDateFieldHandle);

Above that is

which pulls in the following:
jQuery(document).ready(function(){
    $("#fields-cal37_choose_dates_button").click( function() { 
        alert('Clicked the button');
...
        var start_date = new Date( jQuery("#"+startDateFieldHandle).val() );

The alerts happen in the correct sequence, but nevertheless my guess is that because

**Tags:** plugin-development, javascript, custom-fieldtype, garnish


---

## 1 answers

### Answer by username_1 on 2018-05-24. Score: 2 | Accepted answer

Keep in mind Craft parses the html of your field, it won't be used directly, thus the ID of your field can't be "#"+startDateFieldHandleunless you ignored Crafts methods or modified it in another way. Your fields ID will be more like
id="fields-{{the id you specified}}"

Thus you should make sure you used the correct selector like
jQuery("#fields-"+startDateFieldHandle)

usually your order should be fine.. If you want to pass certain variables to Javascript you should do that in Twig because Craft::$app->View->registerJs($js); won't pass variables in a global scope (you can't access them in your JS files in certain cases).
However you should avoid using those globals in Craft. It's better to create a custom Garnish object for the logic
Craft::$app->getView()->registerJs('new Garnish.MyAwesomeField(id, options)');

That will make sure everything is initialized and ready to use
Your js could look like this
Garnish.MyAwesomeField = Garnish.Base.extend(
    {
        $theOtherField: null,
        $field: null,
        options: {},
        init: function (fieldId, settings) {
            this.options = $.extend({}, Garnish.MyAwesomeField.defaults, settings);
            this.$theOtherField = $('#' + this.options.fieldSelector + this.options.theOtherFieldHandle);
            this.$field = $('#' + this.options.fieldSelector + fieldId);
            this.addListener(this.$field, 'click', $.proxy(this, 'clickEvent'));
        },
        clickEvent: function(){
            alert( this.$theOtherField.val() );

        }
    },
    {
        defaults:{
            fieldSelector: 'fields-',
            otherFieldHandle: ''
        }
    }
);

> **Comments:**
> **username_0**: Sorry, I got pulled away a few days. Thank you so much, Robin, for the time and care you put into answering this question. I really appreciate it!  
> **username_0**: I'm trying to wrap my head around this Garnish object. My custom "field" is a button that posts to a controller which sends back some mini-ajax-calendars for inserting and deleting events from the calendar.  
> **username_0**: So this garnish object gives a place to keep some information, and it should be updated correctly, and it also can provide a listener for the the click event? And in the php preceding this, I set `$theOtherField = 'startDateField'`  
> **username_1**: "o this garnish object gives a place to keep some information, and it should be updated correctly, and it also can provide a listener for the the click event?" -> yes.... You can insert all needed options via PHP and pass it to the object like in my example. `options` will be an array of your settings like the other field handle or whatever you need  
> **username_0**: In your garnish.js, you use `this.$field`. Why not hardcode this as `this.fieldId` ?  
> **username_1**: Because you need the actual html element in order to bind events  
> **username_0**: I'm really slow at this. The `Garnish.MyAwesomeField = Garnish.Base.extend...` stuff goes in my `src/resources/occurrencesField.js` which is where the button click js lived, and all that button-click js just goes inside the skeleton clickEvent you provided?  
> **username_1**: You can place the files wherever you like. There are no restrictions. I'm not sure what a `button-click` js is. You'll need to attach an accessible function as event listener to your button. The most elegant way to do this on global level is within a garnish class like I showed. It doesn't matter where that garnish class is or where it comes from. This is actually the only about js scopes and how you should always use Javascript - not really about Craft  
> **username_0**: Yes, it's been almost 3 years since I've done any javascript, and wrapping my mind around the interplay between php and javascript has taken me a while to remember. Thank you so much for all the help! This part is more or less working. Now on to the controller!  

---

